I've written an endless loop in which I want to send a User Message every 5 seconds. Therefore I wrote a thread which waits for 5 seconds and then sends the Message received by the readLine() Method. If the user doesn't give any input the loop doesn't go on because of the readLine() Method waiting for input. So how can I cancel the readLine() Method?
while (true) {
new Thread() {
#Override
public void run() {
try {
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < 5000) {
}
toClient.println(serverMessage);
clientMessage = fromClient.readLine();
System.out.println(clientName + ": " + clientMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
serverMessage = input.readLine();
}
This looks to be a producer-consumer type problem and I would structure this entirely differently since this fromClient.readLine(); is blocking and thus should be performed within another thread.
So consider reading the user input in another thread into a data structure, a Queue<String> such as a LinkedBlockingQueue<String>, and then retrieve String elements from the queue in the code above every 5 seconds, or nothing if no elements are held in the queue.
Something like....
new Thread(() -> {
while (true) {
try {
blockingQueue.put(input.readLine());
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
try {
while (true) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
String input = blockingQueue.poll();
input = input == null ? "" : input;
toClient.println(input);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
Side notes: don't call .stop() on a thread as that is a dangerous thing to do. Also avoid extending Thread.
Related
I java a java method, which makes a connection to a web service.
Sometimes this method takes too long to make the connection.
I want for example it it takes longer than 5 seconds, then to stop the current procedure and restart all over for 3 more times. If all times fail, then abort completely.
I have written the following until now:
private ConnectionInterface connectWithTimeout() throws MalformedURLException, Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException, MalformedURLException, Exception {
return connectWithNoTimeout(); //This is the method that takes to long. If this method takes more than 5 seconds, I want to cancel and retry for 3 more times. Then abort completely.
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
System.out.println( "Timeout Occured");
} catch (InterruptedException e) {
System.out.println( " "InterruptedException Occured");
} catch (ExecutionException e) {
System.out.println( ""ExecutionException Occured");
} finally {
future.cancel(true); // here the method gets canceled. How do I retry it?
}
System.out.println( "Connected !!");
return connectWithNoTimeout();
}
private ConnectionInterface connectWithNoTimeout() throws MalformedURLException, Exception {}
Your method already has a 5 seconds timeout. All you need to do now is to add some kind a loop with 3 repeats. You need a counter of timeouts and a break after successful attempt. Not sure what you want to do when other exceptions happen, added breaks there as well. Following code should do the job:
private ConnectionInterface connectWithTimeout() throws MalformedURLException, Exception {
int repeatCount = 0;
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException, MalformedURLException, Exception {
return connectWithNoTimeout(); //This is the method that takes to long. If this method takes more than 5 seconds, I want to cancel and retry for 3 more times. Then abort completely.
}
};
while (repeatCount < 3){
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
break;
} catch (TimeoutException ex) {
repeatCount++;
System.out.println( "Timeout Occured");
} catch (InterruptedException e) {
System.out.println( " "InterruptedException Occured");
break;
} catch (ExecutionException e) {
System.out.println( "ExecutionException Occured");
break;
} finally {
future.cancel(true); // here the method gets canceled. How do I retry it?
}
}
System.out.println( "Connected !!");
return connectWithNoTimeout();
}
First of all, I'd put the execution of that long command into a new thread so it will not block the Main Thread with the UI etc.
an approach:
Thread thr = new Thread() {
public void run() {
boolean error =false;
boolean success=false;
int time =0;
try {
while(tries<3&&!success){
//HERE GOES YOUR METHOD (connectWithNoTimeout(); ?)! Make sure to make the boolean "Success" = true if the connection is established
while (!error&&time<3) {
time++;
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
};
It's mostly written by hand, you need to make changes, copy & paste will not work
I have an executor service that submits x amount of threads concurrently to do a long task. I need to be able to stop all the current threads that are running and prevent queued tasks from starting. I am trying to implement a way to handle stopping threads that are waiting for a synchronized method in which the runnable passes a list of strings back to the interface that called it.
#Override
public synchronized void FilterResults(List<String> Results) {
//System.out.println("Result found: " + Results.size());
try {
Set<String> hs = new HashSet<>();
hs.addAll(Results);
Results.clear();
Results.addAll(hs);
for (String tempURL : Results) {
//System.out.println("Found url: " + tempURL);
if (!isCompleted(tempURL) && !isQueued(tempURL) && !isRunning(tempURL)) {
System.out.println("Added: " + tempURL + " to queue.");
queueLink(tempURL);
startNewThread(tempURL);
}
}
}catch(Exception e) {
}
return;
}
private synchronized void startNewThread(String seedURL) {
if (!isCompleted(seedURL) && !isRunning(seedURL) ) {
if (completedSize("") + runningSize() > 99) {
Stop();
}
String tempProxy = "";
String tempPort = "";
if (UseProxies) {
String Proxy = grabFreeProxy();
String[] splitProxy = Proxy.split(":");
tempProxy = splitProxy[0]; // 004
tempPort = splitProxy[1]; // 034556
}
//System.out.println("Proxy: " + tempProxy);
//System.out.println("Port: " + tempPort);
execService.submit(new Crawl(seedURL, this, tempProxy, tempPort, UseProxies));
removeFromQueue(url);
}
}
#Override
public Collection<String> Stop() {
try {
execService.shutdown();
if (execService.awaitTermination(45, TimeUnit.SECONDS)) {
System.out.println("task completed");
} else {
execService.shutdownNow();
}
} catch (InterruptedException e) {
}
return PROFILES;
}
The Runnable
public class Crawl implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted() && shutdown == false) {
try {
//System.out.println(crawler.queueSize());
Thread.sleep(100);
Crawl(url);
}catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
}
}
public void crawl(){
try {
submitResults(urls); //Calls FilterResults()
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Thread.currentThread().interrupt();
}
crawler.removeUsedProxy(Proxy + ":" + Port);
this.shutdown();
}
}
When I call my shutdown method it takes 45 seconds+ is there anyway to reliably cancel the task without the long wait? This number grows as I have more threads, and since all the threads are blocking waiting to submit the results, it can take some time. If I cancel the task manually I do not care if the results are stored, I just need to be able to cancel. Any ideas?
Update I've tried ExecutorService#shutdownNow. It has not been reliable
when it comes to killing the tasks that are still blocked on the synchronized method.
Looks like you need to use ExecutorService#shutdownNow in case you don't want to wait and finish all the work and you'll receive a list with the tasks that weren't executed. You may use ExecutionService#awaitTermination (with different parameters than 45 seconds) if you want/need to provide a time to wait for the tasks to finish.
Consider this method from one of my handlers at server side
#Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
try {
io.netty.channel.ChannelFuture f = ctx.writeAndFlush("Executing command now...");
System.out.println("command execution future - " + f);
new Thread(new Runnable() {
int i = 4;
#Override
public void run() {
while(i >= 0 ) {
io.netty.channel.ChannelFuture f = ctx.writeAndFlush("beat till command");
System.out.println("beat till command future - " + f);
try {
Thread.sleep(6*1000);
i--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//assume some processing here
Thread.sleep(20 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
ctx.fireChannelRead(msg);
}
In above code when I write to channel in same thread it is immediately sent to the client, i.e. this message ctx.writeAndFlush("Executing command now...") is sent immediately
But when I try the same thing from a different thread, it is not sent immediately( ctx.writeAndFlush("beat till command") ). Also the future DefaultChannelPromise#5aa824c(incomplete) shows that the operation is incomplete. All these calls are deferred I guess and are completed once the main thread is done. Why is that so? Some locks on ctx?
Please tell me what am I doing wrong here?
I have come up with following thread 'halo' to make it connect to db (redis, in this case) and in the event that server fails, would wait for a second and try again. In my unit test class, method is executing, and not long after new thread starts, server will fail. But then this new thread 'halo' is immediately shut down. What am I doing wrong?
// almost infinitely large number of sets, interrupted by server seg-fault
// you gotta try company methods
Thread halo = new Thread(new Runnable() {
#Override
public void run() {
int count = 0;
while (count < Integer.MAX_VALUE) {
if (JedisPoolFactory.getStatus()) {
try {
for (int i = 0; i < 10000; i++) {
master.set(String.format("key_%d", count), String.format("value_%d", count));
System.out.println(master.get(String.format("key_%d", count)));
count++;
}
} catch (JedisConnectionException igr) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {}
}
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException ignrod) {}
}
}
}
});
halo.start();
try {
master.debug(DebugParams.SEGFAULT());
halo.join();
} catch (JedisConnectionException ignored) {
} catch (InterruptedException igr) {}
thread joining should be done outside of exceptions, when master goes segfault it invokes jedisconnectionexception.
I have rewritten this many times but I could not find a solution to this problem for a while. Some other Class writes gps.log file with lines like:
2014-09-02 10:23:13 35.185604 33.859077
2014-09-02 10:23:18 35.185620 33.859048
I am trying to read the last line of the file and update a text field in the user interface. The Thread below is overdriving the CPU into 85-100%.
I keep the file very tiny (100 lines - < 5KB). I have been working with CSV for a long time, and I think reading this file every 3 seconds should not have this footprint on the CPU. Although I have been reading huge CSV files in the past it is the first time I have this issue now that I try to update the User Interface every couple seconds. Am I doing something wrong with how I am updating the text field? Any ideas?
Thanks for looking.
new Thread(new Runnable() {
public void run() {
while (true) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
try {
try { Thread.sleep(3000); } catch (Exception e) { }
BufferedReader gpslog = new BufferedReader(new FileReader("log/gps.log"));
String line = "";
String lastLine = "";
int i=0;
while (line != null) {
i++;
lastLine = line;
line = gpslog.readLine();
}
//System.out.println(lastLine);
gpslog.close();
if (lastLine != null) { txtGPSStatus.setText(lastLine); }
//If more than 100 gps entries, flush the file
if (i>100) {
PrintWriter writer = new PrintWriter("log/gps.log");
writer.close();
}
} catch (IOException e1) {
log.error(e1);
}
}
});
}
}
}).start();
Move
try { Thread.sleep(3000); } catch (Exception e) { }
so it is just after
while(true) {
Then you will run, wait 3 secs, run, etc.
You should get a clear idea of what should be done by the background thread and what the UI thread is for!
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
public void run() {
try {
while (true) {
updateLog();
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
// restore interruption flag
Thread.currentThread().interrupt();
}
}
});
private void updateLog() {
String lastLine = readLastLogLine();
Display.getDefault().syncExec(new Runnable() {
public void run() {
txtGPSStatus.setText(lastLine);
}
});
}