future.cancel does not work - java

I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question:
Why does not terminate the future.cancel(true) method the called Runnable?
After the program wrote the "END" to the output, the "r" Runnable is still running.

The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled, otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
#Override public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};

This is always a little bit misleading: The ExceutorService or even the underlying thread scheduler do not know anything about what the Runnable is doing. In your case they don't know that there is a unconditional loop.
All these methods (cancel, done, ...) are related to manage Threads in the Executor structure. cancel cancels the thread from the point of view of the Executor service.
The programmer must test if the Runnable was canceled and must terminate the run() method.
So in your case (if I remember well) something like this:
public class Test {
public static void main(String[] args) {
FutureTask r = new FutureTask () {
#Override
public void run() {
try {
for (;!isCancelled();) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}

When you cancel a Future whose Runnable has already begun, the interrupt method is called on the Thread that is running the Runnable. But that won't necessarily stop the thread. Indeed, if it's stuck in a tight loop, like the one you've got here, the Thread won't stop. In this case, the interrupt method just sets a flag called the "interrupt status", which tells the thread to stop when it can.
See the Javadoc for the interrupt method of Thread

Future.cancel() will cancel any queued task or will call Thread.interrupt() on your thread if already running.
You need to interrupt your code
It's your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.

Related

ScheduledFuture.get() is still blocked after Executor shutdown

I want to run some periodic task in background and I want to do it right.
So I schedule my task with ScheduledExecutorService.scheduleWithFixedDelay(..) and call ScheduledFuture.get() on the separate thread to control the life of the task, catch uncaught exceptions from it and get notified if the task is cancelled.
The problem is that if ScheduledExecutorService.shutdown() is called while the task is executing, than ScheduledFuture does not get notified and its get() method stays blocked forever.
And here comes the simple code to illustrate the problem:
public final class SomeService {
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private final SomePeriodicTask task = new SomePeriodicTask();
private ScheduledFuture<?> future;
public void start() {
future = executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
final Runnable watchdog = new Runnable() {
#Override
public void run() {
try {
future.get();
} catch (CancellationException ex) {
System.out.println("I am cancelled");
} catch (InterruptedException e) {
System.out.println("I am interrupted");
} catch (ExecutionException e) {
System.out.println("I have an exception");
}
System.out.println("Watchdog thread is exiting");
}
};
new Thread(watchdog).start();
}
public void shutdownAndWait() {
System.out.println("Shutdown requested");
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) { //BTW When and why could this happen?
System.out.println("Waiting for shutdown was interrupted");
}
System.out.println("Executor is shutdown " + executor.isShutdown());
}
}
First, simple task which returns quickly
final class SomePeriodicTask implements Runnable {
#Override
public void run() {
System.out.print("I am just doing my job...");
System.out.println("done");
}
}
If we run it like this
public static void main(String[] args) throws InterruptedException {
SomeService service = new SomeService();
service.start();
Thread.sleep(3000);
service.shutdownAndWait();
System.out.println("Future is cancelled " + service.future.isCancelled());
System.out.println("Future is done " + service.future.isDone());
}
then the output is
I am just doing my job...done
I am just doing my job...done
I am just doing my job...done
Shutdown requested
I am cancelled
Watchdog thread is exiting
Executor is shutdown true
Future is cancelled true
Future is done true
totally as expected.
But if we modify the task to simulate some heavy job
final class SomePeriodicTask implements Runnable{
#Override
public void run() {
System.out.print("I am just doing my job...");
try {
Thread.sleep(1500); //Heavy job. You can change it to 5000 to be sure
} catch (InterruptedException e) {
System.out.println("Task was interrupted");
}
System.out.println("done");
}
}
so that the call to shutdown() happens while the task is executing... then the output is
I am just doing my job...done
I am just doing my job...Shutdown requested
done
Executor is shutdown true
Future is cancelled false
Future is done false
So what happened here... Executor is shutting down, as expected. It lets the current task to finish its job, as expected. We see that executor did finish shutting down, but our ScheduledFuture did not get cancelled and its get() method is still blocked and the watchdog thread prevents JVM from exiting and hangs forever.
Of course there are workarounds. For example I can call future.cancel(false) manually before shutdown or make watchdog a daemon thread or even try to schedule shutdown of Executor by himself so that it does not overlap with running task... But all of above have drawbacks and when code will get more complicated things can go sideways.
And anyway, I am seeking for your expert opinion because I will have no peace until I understand why it doesn't behave like it should. If it is a bug in jdk it must be reported. If I misunderstand something and my code is wrong, I must know it...
Thanks in advance
The first thing to understand is that for a periodic task, a normal completion does not turn the state of the Future to done as it expects to be rescheduled and possibly rerun.
This interferes with the semantics of Executor.shutdown; it will cancel all pending tasks but let the currently running tasks complete. So your currently running task completes normally and doesn’t set its state to done as it never does, but isn’t rescheduled because the executor has been shut down.
Even if you use shutdownNow it will interrupt the currently running tasks but not cancel them and since your task catches the InterruptedException and completes earlier but normally, there will be no state transition to done.
The best place to add the desired behavior of cancelling even tasks that completed normally upon shutdown is the Executor implementation; just change the line
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
to
private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1) {
#Override
protected void afterExecute(Runnable r, Throwable t) {
if(t==null && isShutdown() && r instanceof RunnableScheduledFuture<?>)
{
RunnableScheduledFuture<?> rsf = (RunnableScheduledFuture<?>)r;
if(rsf.isPeriodic()) rsf.cancel(false);
}
};
};

Recover from exceptions in ExecutorService

I use a the ExecutorService to execute my logic. As shown below , the run method should execute in a infinite loop. In short the run method is a message consumer which should remove messages from a queue and process the messages. However, the doSomething() method encounters an Exception, and never returns. After analysis, I realise that there was a NullPointer somewhere in the doSomething() method. While, I have taken care of that exception, how do I ensure that loop never terminates in-spite of any runtime exceptions. I cannot afford my Runnable task to be non-functional. It stops the entire functionality.
ExecutorService service = Executors.newSingleThreadExecutor()
service.submit(new Runnable(){
public void run(){
while(true){
doSomething();
}
}
})
Try catching exception within your loop like below:
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(new Runnable(){
public void run(){
while(true){
try {
doSomething();
} catch (Exception e) {
//log exception etc...
}
}
}
});
Just surround the run method's content with a try/catch that catches every exception.
ExecutorService service = Executors.newSingleThreadExecutor()
service.submit(new Runnable(){
public void run(){
while(true){
try {
doSomething();
} catch (Exception e) {
handleException();
}
}
}
})

Method call from thread does not finish - How to end the thread - Workaround

I have a following code.
ReadWriteLock someLock = new ReentrantReadWriteLock();
Condition someCondition = someLock.writeLock().newCondition();
public someMethod() {
// do some stuff
someCondition.await(); //Lock here.
System.out.prinltn("This never prints");
}
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
When the thread calls the method someMethod() it gets executed. But since there is an await() method on that function. It never ends / it does not print 'This never prints', unless its woken up by singnalAll(). But I want the thread to be finished once its executed.
I cannot refactor the whole thing. I just need a workaround to this problem. Its used in Swing application. So thread is important.
I think, this will do:
Thread thread =
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
});
thread.start( );
final long reasonableTimeout = ...;
thread.join( reasonableTimeout );
// THIS WILL SHAKE IT UP
thread.interrupt( );
thread.join( );
// At this point, it is guaranteed that the thread has finished
I am not sure if I understood your question correctly but I think you want to start the someMethod() function and then make the caller exit without waiting for someMethod() to finish. This means you are basically branching your execution flow into two, one where the someMethod() running waiting for its due awakening and the other where the caller just continues on(which it will need to do if you want it to finish) after calling someMethod(). To do this you will have to run someMethod() in a separate thread. Something like this.
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
new Thread(){
public void run(){
someMethod();
}
}.start();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
Two ways you can sort this out.
1) Design your task with Interruption Policy
Do a defensive coding. If your task is interrupted by any means, the program should know how to deal with that.
2) Add a POISON PILL as in this example, Once you
public someMethod() {
while(condition predicate){
someCondition.await(TIME_OUT); //Lock here.
}
//ADD Poison pill here
System.out.prinltn("This never prints");
}
As Per Java Concurrency in Practice
When using condition waits (Object.wait or Condition.await):
1)Always have a condition predicate some test of object state that must hold before
proceeding;
2)Always test the condition predicate before calling wait, and again after returning from
wait;
3)Always call wait in a loop;
4)Ensure that the state variables making up the condition predicate are guarded by the lock
associated with the condition queue;
5) Hold the lock associated with the the condition queue when calling wait, notify, or
notifyAll; and
6)Do not release the lock after checking the condition predicate but before acting on it.

Interrupting looped threads in Java

I'm trying to understand how threads work in Java and currently investigating how to implement looped threads that can be cancelled. Here's the code:
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
#Override
public void run() {
System.out.println("THREAD: started");
try {
while(!isInterrupted()) {
System.out.printf("THREAD: working...\n");
Thread.sleep(100);
}
} catch(InterruptedException e) {
// we're interrupted on Thread.sleep(), ok
// EDIT
interrupt();
} finally {
// we've either finished normally
// or got an InterruptedException on call to Thread.sleep()
// or finished because of isInterrupted() flag
// clean-up and we're done
System.out.println("THREAD: done");
}
}
};
t.start();
Thread.sleep(500);
System.out.println("CALLER: asking to stop");
t.interrupt();
t.join();
System.out.println("CALLER: thread finished");
}
The thread I create is indended to be interrupted sooner or later. So, I check isInterrupted() flag to decide whether I need to go on and also catch InterruptedException to handle cases when I'm in a kind of waiting operation (sleep, join, wait).
Things I'd like to clarify are:
Is it fine to use interruption mechanism for this kind of task? (comparing to having volatile boolean shouldStop)
Is this solution correct?
Is it normal that I swallow InterruptedException? I'm not really interested what was the piece of code where someone asked my thread to interrupt.
Are there any shorter ways to solve this problem? (the main point is having 'infinite' loop)
EDIT
Added call to interrupt() in catch for InterruptedException.
I am answering no. 3:
Basically the question is: What purpose does an Interrupted exception have? It tells you to stop blocking (e.g. sleeping) and return early.
There are two ways dealing with an InterruptedException:
Rethrow it, so the thread remains interrupted
set Thread.currentThread.interrupt() again and do your cleanup work. This way you can be sure that another method in your thread starting to sleep will throw again
Simply swallowing an InterruptedException is not a good idea regarding the purpose of such an interrupt which is to finally terminate. But you are only asked to interrupt so you still have time to clean up.
In this case this might be an 'overreaction' of myself, but typically such code is much more complicated and how do you know, that some follow-up-code in this Thread would not call a blocking method again?
EDIT
Otherwise I think what you're doing is fine. For me a bit surprising, though, because I never saw anyone in his own code actually doing it.
And interesting article explaining why can be found here: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html
Yes, it's fine. You should document how a Thread/Runnable must be stopped. You could add a dedicated stop method on your Runnable implementation that encapsulates the stopping mechanism. Either use interrupt, or use a dedicated boolean value, or both.
Yes, except the good practice is to restore the interrupt status when catching InterruptedException: Thread.currentThread().interrupt();
No, you should restore the interrupt status
None that I'm aware of
1) The way in your example is preferable to using a volatile flag (which is redundant since you already have the interrupted flag), according to the Java Concurrency in Practice book. It is how InterruptedExceptions were intended to be used.
2) Yes
3) you can eat the exception as long as you restore the interrupt flag status. The exception doesn't represent an error so eating it doesn't lose any information, it is purely a means of transferring control. (Restoring the interrupt flag status is important for cases where you have nested control structures that each need to be informed that the thread is cancelling, for a simple example like yours it's good form but if it's missing it won't hurt anything.)
4) no
It's fine to use Interruption, but use them well. You have to re-throw Thread.currentThread().interrupt() in your catch. Here is a piece of code showing why :
public class MyThread extends Thread {
private static boolean correct = true;
#Override
public void run() {
while (true) {
// Do Something 1
for (int i = 0; i < 10; i++) { // combined loop
// Do Something 2
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt(); // reinterrupting
System.out.println("First Catch");
break; // for
}
}
try {
// Do Something 3
System.out.print("before sleep, ");
Thread.sleep(1000);
System.out.print("After sleep, ");
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt();
System.out.println("Second catch");
break; // while
}
}
System.out.println("Thread closing");
}
private static void test() throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(2500);
t.interrupt();
t.join();
System.out.println("End of Thread");
}
public static void main(String[] args)
throws InterruptedException {
test();
correct = false; // test "bad" way
test();
}
}
Another thing is, Interruptions don't always work when waiting on InputStreams. You then can use (for some) InterruptedIOException, but it won't always work. To understand these cases, you might want to try this piece of code :
public class Mythread extends Thread {
private InputStream in;
public Mythread(InputStream in) {
this.in = in;
}
#Override
public void interrupt() {
super.interrupt();
try {
in.close(); // Close stream if case interruption didn't work
} catch (IOException e) {}
}
#Override
public void run() {
try {
System.out.println("Before read");
in.read();
System.out.println("After read");
} catch (InterruptedIOException e) { // Interruption correctly handled
Thread.currentThread().interrupt();
System.out.println("Interrupted with InterruptedIOException");
} catch (IOException e) {
if (!isInterrupted()) { // Exception not coming from Interruption
e.printStackTrace();
} else { // Thread interrupted but InterruptedIOException wasn't handled for this stream
System.out.println("Interrupted");
}
}
}
public static void test1() // Test with socket
throws IOException, InterruptedException {
ServerSocket ss = new ServerSocket(4444);
Socket socket = new Socket("localhost", 4444);
Thread t = new Mythread(socket.getInputStream());
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void test2() // Test with PipedOutputStream
throws IOException, InterruptedException {
PipedInputStream in = new PipedInputStream(new PipedOutputStream());
Thread t = new Mythread(in);
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void main(String[] args) throws IOException, InterruptedException {
test1();
test2();
}
}

Java: set timeout on a certain block of code?

Is it possible to force Java to throw an Exception after some block of code runs longer than acceptable?
Here's the simplest way that I know of to do this:
final Runnable stuffToDo = new Thread() {
#Override
public void run() {
/* Do stuff here. */
}
};
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(5, TimeUnit.MINUTES);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
/* Handle the timeout. Or ignore it. */
}
if (!executor.isTerminated())
executor.shutdownNow(); // If you want to stop the code that hasn't finished.
Alternatively, you can create a TimeLimitedCodeBlock class to wrap this functionality, and then you can use it wherever you need it as follows:
new TimeLimitedCodeBlock(5, TimeUnit.MINUTES) { #Override public void codeBlock() {
// Do stuff here.
}}.run();
I compiled some of the other answers into a single utility method:
public class TimeLimitedCodeBlock {
public static void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
runWithTimeout(new Callable<Object>() {
#Override
public Object call() throws Exception {
runnable.run();
return null;
}
}, timeout, timeUnit);
}
public static <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<T> future = executor.submit(callable);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
return future.get(timeout, timeUnit);
}
catch (TimeoutException e) {
//remove this if you do not want to cancel the job in progress
//or set the argument to 'false' if you do not want to interrupt the thread
future.cancel(true);
throw e;
}
catch (ExecutionException e) {
//unwrap the root cause
Throwable t = e.getCause();
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof Exception) {
throw (Exception) t;
} else {
throw new IllegalStateException(t);
}
}
}
}
Sample code making use of this utility method:
public static void main(String[] args) throws Exception {
final long startTime = System.currentTimeMillis();
log(startTime, "calling runWithTimeout!");
try {
TimeLimitedCodeBlock.runWithTimeout(new Runnable() {
#Override
public void run() {
try {
log(startTime, "starting sleep!");
Thread.sleep(10000);
log(startTime, "woke up!");
}
catch (InterruptedException e) {
log(startTime, "was interrupted!");
}
}
}, 5, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
log(startTime, "got timeout!");
}
log(startTime, "end of main method!");
}
private static void log(long startTime, String msg) {
long elapsedSeconds = (System.currentTimeMillis() - startTime);
System.out.format("%1$5sms [%2$16s] %3$s\n", elapsedSeconds, Thread.currentThread().getName(), msg);
}
Output from running the sample code on my machine:
0ms [ main] calling runWithTimeout!
13ms [ pool-1-thread-1] starting sleep!
5015ms [ main] got timeout!
5016ms [ main] end of main method!
5015ms [ pool-1-thread-1] was interrupted!
Yes, but its generally a very bad idea to force another thread to interrupt on a random line of code. You would only do this if you intend to shutdown the process.
What you can do is to use Thread.interrupt() for a task after a certain amount of time. However, unless the code checks for this it won't work. An ExecutorService can make this easier with Future.cancel(true)
Its much better for the code to time itself and stop when it needs to.
If it is test code you want to time, then you can use the time attribute:
#Test(timeout = 1000)
public void shouldTakeASecondOrLess()
{
}
If it is production code, there is no simple mechanism, and which solution you use depends upon whether you can alter the code to be timed or not.
If you can change the code being timed, then a simple approach is is to have your timed code remember it's start time, and periodically the current time against this. E.g.
long startTime = System.currentTimeMillis();
// .. do stuff ..
long elapsed = System.currentTimeMillis()-startTime;
if (elapsed>timeout)
throw new RuntimeException("tiomeout");
If the code itself cannot check for timeout, you can execute the code on another thread, and wait for completion, or timeout.
Callable<ResultType> run = new Callable<ResultType>()
{
#Override
public ResultType call() throws Exception
{
// your code to be timed
}
};
RunnableFuture<ResultType> future = new FutureTask<>(run);
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(future);
ResultType result = null;
try
{
result = future.get(1, TimeUnit.SECONDS); // wait 1 second
}
catch (TimeoutException ex)
{
// timed out. Try to stop the code if possible.
future.cancel(true);
}
service.shutdown();
}
I can suggest two options.
Within the method, assuming it is looping and not waiting for an external event, add a local field and test the time each time around the loop.
void method() {
long endTimeMillis = System.currentTimeMillis() + 10000;
while (true) {
// method logic
if (System.currentTimeMillis() > endTimeMillis) {
// do some clean-up
return;
}
}
}
Run the method in a thread, and have the caller count to 10 seconds.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
method();
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + 10000;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
// set an error flag
break;
}
try {
Thread.sleep(500);
}
catch (InterruptedException t) {}
}
The drawback to this approach is that method() cannot return a value directly, it must update an instance field to return its value.
EDIT: Peter Lawrey is completely right: it's not as simple as interrupting a thread (my original suggestion), and Executors & Callables are very useful ...
Rather than interrupting threads, you could set a variable on the Callable once the timeout is reached. The callable should check this variable at appropriate points in task execution, to know when to stop.
Callables return Futures, with which you can specify a timeout when you try to 'get' the future's result. Something like this:
try {
future.get(timeoutSeconds, TimeUnit.SECONDS)
} catch(InterruptedException e) {
myCallable.setStopMeAtAppropriatePlace(true);
}
See Future.get, Executors, and Callable ...
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html#get-long-java.util.concurrent.TimeUnit-
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool%28int%29
I created a very simple solution without using any frameworks or APIs. This looks more elegant and understandable. The class is called TimeoutBlock.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* #return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* #param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
example :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
#Override
public void run() {
//TO DO write block of code to execute
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}
This was so much useful for me when i had to connect to a FTP account. Then download and upload stuff. sometimes FTP connection hangs or totally breaks. This caused whole system to go down. and i needed a way to detect it and prevent it from happening . So i created this and used it. Works pretty well.
I faced a similar kind of issue where my task was to push a message to SQS within a particular timeout. I used the trivial logic of executing it via another thread and waiting on its future object by specifying the timeout. This would give me a TIMEOUT exception in case of timeouts.
final Future<ISendMessageResult> future =
timeoutHelperThreadPool.getExecutor().submit(() -> {
return getQueueStore().sendMessage(request).get();
});
try {
sendMessageResult = future.get(200, TimeUnit.MILLISECONDS);
logger.info("SQS_PUSH_SUCCESSFUL");
return true;
} catch (final TimeoutException e) {
logger.error("SQS_PUSH_TIMEOUT_EXCEPTION");
}
But there are cases where you can't stop the code being executed by another thread and you get true negatives in that case.
For example - In my case, my request reached SQS and while the message was being pushed, my code logic encountered the specified timeout. Now in reality my message was pushed into the Queue but my main thread assumed it to be failed because of the TIMEOUT exception.
This is a type of problem which can be avoided rather than being solved. Like in my case I avoided it by providing a timeout which would suffice in nearly all of the cases.
If the code you want to interrupt is within you application and is not something like an API call then you can simply use
future.cancel(true)
However do remember that java docs says that it does guarantee that the execution will be blocked.
"Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled,or could not be cancelled for some other reason. If successful,and this task has not started when cancel is called,this task should never run. If the task has already started,then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted inan attempt to stop the task."
If you want a CompletableFuture way you could have a method like
public MyResponseObject retrieveDataFromEndpoint() {
CompletableFuture<MyResponseObject> endpointCall
= CompletableFuture.supplyAsync(() ->
yourRestService.callEnpoint(withArg1, withArg2));
try {
return endpointCall.get(10, TimeUnit.MINUTES);
} catch (TimeoutException
| InterruptedException
| ExecutionException e) {
throw new RuntimeException("Unable to fetch data", e);
}
}
If you're using spring, you could annotate the method with a #Retryable so that it retries the method three times if an exception is thrown.
Instead of having the task in the new thread and the timer in the main thread, have the timer in the new thread and the task in the main thread:
public static class TimeOut implements Runnable{
public void run() {
Thread.sleep(10000);
if(taskComplete ==false) {
System.out.println("Timed Out");
return;
}
else {
return;
}
}
}
public static boolean taskComplete = false;
public static void main(String[] args) {
TimeOut timeOut = new TimeOut();
Thread timeOutThread = new Thread(timeOut);
timeOutThread.start();
//task starts here
//task completed
taskComplete =true;
while(true) {//do all other stuff }
}
There is a hacky way to do it.
Set some boolean field to indicate whether the work was completed. Then before the block of code, set a timer to run a piece of code after your timeout. The timer will check if the block of code had finished executing, and if not, throw an exception. Otherwise it will do nothing.
The end of the block of code should, of course, set the field to true to indicate the work was done.
There's a very simple option that nobody's mentioned yet:
Duration timeout = Duration.ofMinutes(5);
Thread thread = new Thread(() -> {
// your code here
});
thread.start();
thread.join(timeout.toMillis());
if (thread.isAlive()) {
thread.interrupt();
throw new MyTimeoutException();
}
If the thread running your code block fails to complete within the timeout, it is interrupted and whatever exception you want can be thrown.
It is possible to write code that will simply ignore the interruption and carry on. If you're dealing with this can cannot fix it then there is thread.stop(), but that can break any synchronisation mechanisms that you are relying on. See its deprecation notice.
You can also capture exceptions from the thread:
AtomicReference<Throwable> uncaughtException = new AtomicReference<>();
thread.setUncaughtExceptionHandler((t, ex) -> uncaughtException.setRelease(ex));
// ...
Throwable ex = uncaughtException.getAcquire();
if (ex != null) {
throw ex;
}
I had this problem too, my logs print out with ‘’Unexpected end of stream‘’.and ‘’Could not get a resource from the pool‘’,
I set the timeout of brpop to 30s, redis to 31s, and mysql database connection pool to 300s. For now, this error is not printed on the log, but I don't know if this error will be reported in the future.I don't know if it has a bad effect on my writing to the database

Categories

Resources