I have an infinite loop inside my main, it runs a job which is also an infinite loop, and wait for it to throw an error. Then it sleeps for a given amount of time and starts the task again.
public static void main(String[] args) {
while (true) {
try {
MyClass myClass = new MyClass();
myClass.startInfiniteLoop();
}
catch (SomeException ex) {
try {
Thread.sleep(MyClass.DEFAULT_SLEEP_TIME);
}
catch (InterruptedException ex2) {
System.exit(-1);
}
}
}
}
This works fine, but I wonder if this could be done better, perhaps with an ExecutorService as I (and my IDE) don't like Thread.sleep() in a while (true) loop.
I have read a lot of questions and their answers about ScheduledExecutorService and task management, but I did not find this particular case since it's not really a schedule, I don't know if and when the task if going to end.
You can use a ScheduledExecutorService:
ScheduledExecutorService s=Executors.newScheduledThreadPool(1);
s.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
MyClass myClass = new MyClass();
myClass.startInfiniteLoop();
} catch(SomeException ex) {}
}
}, 0, MyClass.DEFAULT_SLEEP_TIME, TimeUnit.MILLISECONDS);
The key point is to use scheduleWithFixedDelay rather than scheduleAtFixedRate to ensure the specified time elapses between the subsequent executions just like with your sleep approach. However, note that even with “fixed rate” the new execution will not start when the old one has not finished yet. It’s documentation says: “If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.”
Further note that you still have to catch the exception like in my code example as otherwise the executor will cancel the scheduled task once it threw an uncatched exception.
If you can take the MyClass and rework it to have a Runnable that does what only one loop iteration of the MyClass would have done, then you can use a scheduling executor service, telling the service to run the Runnable once every time period.
--- Updated by request of a quick example ---
The following is not strictly correct Java code, it is pesudo-java.
public class MyRepeatingTask implements Runnable {
private final ScheduledThreadpoolExecutor executor;
public MyRepeatingTask(ScheduledThreadpoolExecutor executor) {
this.executor = executor;
}
public void run() {
try {
doMyVariableLengthThing();
// alternatively, you could also schedule a new instance
executor.schedule(this, 1, TimeUnit.SECONDS);
} catch (Exception e) {
cleanup();
}
}
}
and then to start the ball rolling
ScheduledThreadpoolExecutor executor = new ScheduledThreadpoolExecutor(1);
executor.execute(new MyRepeatingTask(executor));
Related
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);
}
};
};
Here's essentially my problem:
while (true) {
if (previous 'doWorkAsync' method is not still in flight) {
doWorkAsync() // this returns immediately
}
wait set amount of time
}
A couple solutions come to mind for me:
Block until doWorkAsync() completes. This is not desirable to me for a few reasons.
It (potentially) results in waiting longer than I really needed to in the 'wait some set amount of time' line (e.g. if doWorkAsync takes 5 seconds, and the set amount of waiting time is 10 seconds, this will result in 15 seconds of waiting between calls, which isn't what I wanted). Of course, I could account for this by waiting less time, but somehow it just feels clunky.
It also ties up this thread unnecessarily. Instead of waiting for this task to come back, this thread could handle other work, like making config updates so the next call to doWorkAsync() has fresh data.
Use a gating mechanism. The easiest implementation that comes to mind is a boolean, set before calls to doWorkAsync(), and unset when doWorkAsync() completes. This is essentially what I'm doing now, but I'm not sure if it's an anti-pattern??
Is #2 the right way to go, or are there better ways to solve this problem?
EDIT: If it helps, doWorkAsync() returns a ListenableFuture (of guava).
The original question may not have been 100% clear. Here's the crux. If the async request finishes before the given timeout, this code will always work. However, if the async task takes SET_AMOUNT_OF_TIME + epsilon to complete, then this code will sleep twice as long as necessary, which is what I'm trying to avoid.
The simplest way to do this is using the wait and notifyAll methods already in Java. All you need to do is use an AtomicBoolean as a flag and block on it until the another Thread tells you something has changed.
The difference between that and your approach is that a blocked thread doesn't do anything whereas a polling thread uses CPU time.
Here is a simple example using two Threads - the Runnable "First" is submitted and it waits on done until the Runnable "Second" notifies that it has changed the flag.
public class App {
private static final AtomicBoolean done = new AtomicBoolean(false);
private static final class First implements Runnable {
#Override
public void run() {
while (!done.get()) {
System.out.println("Waiting.");
synchronized (done) {
try {
done.wait();
} catch (InterruptedException ex) {
return;
}
}
}
System.out.println("Done!");
}
}
private static final class Second implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
return;
}
done.set(true);
synchronized (done) {
done.notifyAll();
}
}
}
public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new First());
Thread.sleep(1000);
executorService.submit(new Second());
executorService.shutdown();
}
}
The sleep calls are just to show that a task of arbitrary length can take place, obviously they are not required.
The thing to note is that First prints "waiting" every time it enters the loop and, if you run the code, it only prints it once. The second thing to note is that First reacts to the changing of the flag immediately as it is told to awake and recheck when the flag is changed.
I have used return in the InterruptedException blocks, you may want to used Thread.currentThread().interrupt() instead so that the process doesn't die if it's spuriously interrupted.
A more advanced approach is to use Lock and Condition
public class App {
private static final Lock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static final class First implements Runnable {
#Override
public void run() {
lock.lock();
System.out.println("Waiting");
try {
condition.await();
} catch (InterruptedException ex) {
return;
} finally {
lock.unlock();
}
System.out.println("Done!");
}
}
private static final class Second implements Runnable {
#Override
public void run() {
lock.lock();
try {
Thread.sleep(1000);
condition.signalAll();
} catch (InterruptedException ex) {
return;
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new First());
Thread.sleep(1000);
executorService.submit(new Second());
executorService.shutdown();
}
}
In this situation First acquires a lock on the Lock object the immediately calls await on the Condition. The releases the lock and blocks on the Condition.
Second then acquires a lock on the Lock and calls signalAll on the Condition which awakes First.
First then reacquires the lock and continues execution, printing "Done!".
EDIT
The OP would like to call the method doWorkAsync with a specified period, if the method takes less time than the period then the process has to wait. If the method takes longer then the method should be called again immediately after.
The task needs to be stopped after a certain time.
At no point should the method be running more than once simultaneously.
The easiest approach would be to call the method from a ScheduledExecutorService, the Runnable would wrap the method and call get on the Future - blocking the scheduled executor until it is done.
This guarantees that the method is called with at least WAIT_TIME_BETWEEN_CALLS_SECS delay.
Then schedule another task that kills the first one after a set time.
final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
final Future<?> taskHandle = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
final ListenableFuture<Void> lf = doWorkAsync();
try {
doWorkAsync().get();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
}, 0, WAIT_TIME_BETWEEN_CALLS_SECS, TimeUnit.SECONDS);
scheduledExecutorService.schedule(new Runnable() {
#Override
public void run() {
taskHandle.cancel(false);
}
}, TOTAL_TIME_SECS, TimeUnit.SECONDS);
The best solution would be call the raw Runnable on a ScheduledExecutorService rather than calling it on another executor and blocking on the ListenableFuture.
Think what you are looking for is The Reactor Pattern.
Is there a reason you don't want these things running at the same time? If what you want to do is chain them, you could use Futures. Akka has Composable Futures and mappable ones.
I have a processing loop of the form
while (true) {
doWork();
Thread.sleep(SLEEP_INTERVAL);
}
I want to make a Runnable out of this that can play well with ExecutorService and which will exit when ExecutorService.shutdownNow() is called.
I'm looking to write it this way:
public WorkerTask implements Runnable
{
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
doWork();
try {
Thread.sleep(SLEEP_INTERVAL);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
Simple testing shows it at least appearing to work in that the task gets interrupted and will exit and the ExecutorService will shut down, and appears to do so whether the interrupt arrives while doWork() is processing or during the sleep. (By varying how much work doWork() does and how big SLEEP_INTERVAL is I can pretty much control where the interrupt happens).
But when I google I see examples using Thread.interrupted() as well as Thread.currentThread().isInterrupted(). I understand that the former clears the interrupted flag while the latter leaves it, but is there any other difference I need to care about?
I also see versions where the result of Thread.currentThread().isInterrupted() or Thread.interrupted() is stored in a volatile variable and that variable is used as the while loop test condition. Is that just a style or is there a need to do that? In what I've written do I have to worry that somehow something can clear the interrupt flag between when it is set (whether by being received when the thread is live, or by my catching InterruptedException and reasserting the flag) and when Thread.currentThread().isInterrupted() is called in the loop test?
Your code looks fine to me. Introducing an additional volatile variable would be unnecessary complexity: the interrupt status does the job.
The recommended way, in Java Concurrency in Practice, to deal with interrupts in tasks is to either throw an InterruptedException (this is doable if the task is a Callable and not a Runnable), or to make sure the interrupt status is set and to exit from the task ASAP. Your code does that well.
Could you take a look at ScheduledExecutorService if it matches your requirements:
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() { beeperHandle.cancel(true); }
}, 60 * 60, SECONDS);
}
}}
Basically you should take advantage of java.util.concurrent libraries here .You should submit your task via ExecutorService.submit()and then call blocking methods like Future.get() , then you can be sure that those methods will respond to interruption as soon as possible by throwing an ExecutionException() .You probably should get rid of that Thread.sleep() since it is doing nothing . You want to sniff an interrupt as quickly as possible .You possibly also want to wait for a timeout in case your task is doing something inifinitely . So if the task terminates with a TimeOutException , the task is cancelled via its Future.
I call cancel() unconditionally since cancelling a completed task has no effect.
In that case you can do some thing like :
public static void main(String[] args) {
WorkerTask runnable;
TimeUnit unit;
Future<?> task = executor.submit(workerTask);
try{
task.get(timeout,unit);
} catch(TimeoutException e){
}catch(ExecutionException e){
throw e.getCause();
} finally{
//Harmless if the task already completed
task.cancel(true);
}
}
}
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
I am trying to port code from using java timers to using scheduledexecutorservice
I have the following use case
class A {
public boolean execute() {
try {
Timer t = new Timer();
t.schedule (new ATimerTask(), period, delay);
} catch (Exception e) {
return false;
}
}
}
class B {
public boolean execute() {
try {
Timer t = new Timer();
t.schedule (new BTimerTask(), period, delay);
} catch (Exception e) {
return false;
}
}
}
Should I just replace Timer instances in class A and class B with ScheduledExecutorService and make the ATimerTask and BTimerTask class to a Runnable class , for e.g
class B {
public boolean execute() {
try {
final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
scheduler.scheduleWithFixedDelay (new BRunnnableTask(), period, delay);
} catch (Exception e) {
return false;
}
}
}
Is this correct.
EDIT: One of the primary motivation of porting is since runtime exceptions thrown in TimerTask kill that one thread and it cannot be scheduled further. I want to avoid the case so that ieven if I have runtime exception the thread should keep on executing and not halt.
NOTE: The way you did this will leak threads!
If your class B will be kept around and each instance will eventually be closed or shut down or released, I would do it like this:
class B {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public boolean execute() {
try {
scheduler.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
return true;
} catch (Exception e) {
return false;
}
}
public void close() {
scheduler.shutdownNow();
}
}
If you will not do this kind of cleanup on each instance, then I would instead do this:
class B {
static final ScheduledExecutorService SCHEDULER = Executors.newCachedThreadPool();
public boolean execute() {
try {
SCHEDULER.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
return true;
} catch (Exception e) {
return false;
}
}
}
Each ExecutorService you allocate in your code allocates a single Thread. If you make many instances of your class B then each instance will be allocated a Thread. If these don't get garbage collected quickly, then you can end up with many thousands of threads allocated (but not used, just allocated) and you can crash your whole server, starving every process on the machine, not just your own JVM. I've seen it happen on Windows and I expect it can happen on other OS's as well.
A static Cached thread pool is very often a safe solution when you don't intend to use lifecycle methods on the individual object instances, as you'll only keep as many threads as are actually running and not one for each instance you create that is not yet garbage collected.
It looks ok. Depending on what you're doing, you may want to keep executor service around as a member so you can use it again. Also, you can get a ScheduledFuture back from the scheduleXX() methods. This is useful because you can call get() on it to pull any exceptions that occur in the timed thread back to your control thread for handling.
There is currently no good way to handle repeating tasks in the Executors framework.
It really wasn't designed with this use case in mind, and there is no realistic way to avoid swallowing exceptions.
If you really must use it for repeating tasks, each scheduling should look something like this:
scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
.. your normal code here...
} catch (Throwable t) {
// handle exceptions there
}
}
}, period, delay);