Properly writing task that ExecutorService.shutdownNow() can stop? - java

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);
}
}
}

Related

Spontaneous execution of code in periodically running thread

I have a thread which executes code periodically, e. g. every 10 seconds. I'd like to have the option to also invoke the same code in a spontaneous way and not have to wait 10 seconds. But the code of the automatic and spontaneous execution must never run concurrently, instead they should run in sequence if the user presses the execute button while the thread is invoking the same method.
Does anyone know a good pattern or even a class that can address this kind of requirement?
First thing that comes to mind would be to make the work method synchronized. But in that case the manual execution (e. g. button press) is blocked and has to wait until the method in the thread is finished. Is there a better approach without blocking?
Example:
public class Executor extends Thread {
// endless loop, executes work method periodically with pause inbetween
#Override
public void run() {
while( true) {
work( "automatic");
pause(10000);
}
}
// Working method that's executed periodically or manually
private synchronized void work( String text) {
System.out.println( "Working " + text + " " + System.currentTimeMillis());
}
// helper method that pauses the thread
private static void pause( long sleepMs) {
try {
Thread.sleep(sleepMs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// start automatic execution
Executor executor = new Executor();
executor.start();
// pause a while
pause(1000);
// manual execution
executor.work( "manual");
}
}
Edit: Solution for my requirement:
public class ScheduledExecutor {
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
executor.scheduleWithFixedDelay(new Work("auto"), 0, 10, TimeUnit.SECONDS);
Thread.sleep(1000);
executor.execute(new Work("manual"));
}
public static class Work implements Runnable {
String text;
public Work(String text) {
this.text = text;
}
#Override
public void run() {
System.out.println("Working " + text + " " + System.currentTimeMillis());
}
}
}
I would create a new, single-thread executor service:
ExecutorService executorService = Executors.newFixedThreadPool(1);
Then, I would set up a timer that feeds the executorService a task once every 10 seconds.
new Timer(10000, new ActionListener {
public void actionPerformed(ActionEvent evt) {
executorService.execute(() -> doWhatever());
}
}).start();
Finally, you can call executorService.execute(() -> doWhatever()); in your button press handler, or wherever else you want in your code.
Only one activation of doWhatever() will run at a time because the executorService has only one thread on which to run them. And, your button press handler will never have to wait, because it does nothing but put a new object on a queue.
I have a thread which executes code periodically, e. g. every 10 seconds. I'd like to have the option to also invoke the same code in a spontaneous way and not have to wait 10 seconds.
A simple way to do this in your code is not to pause by using Thread.sleep(...) but rather do wait(...). Then whenever you want the command to wakeup and run manually it just does a notify().
So you code would look something like:
while( true) {
work( "automatic");
synchronized (this) {
try {
// wait for a bit but allow someone else to awake us to run manually
wait(10000);
} catch (InterruptedException ie) {
// always a good pattern
Thread.currentThread().interrupt();
return;
}
}
}
Then when you want to have it run manually you do:
synchronized (executor) {
executor.notify();
}
The notify will awaken the thread immediately so that it can run it's task. The work method then does not need to be synchronized because only the Executor thread is running it.
NOTE: As pointed out by #shinobi, using wait() like this could suffer from spurious wake-ups which can happen with certain OS thread implementations.
Lastly, it is a better practice to make Executor implement Runnable as opposed to extending Thread.
Share a semaphore between the server thread (the one that executes the task) and client threads (the ones that need to trigger immediate execution):
Semaphore sem = new Semaphore( 0 );
The server thread needs to execute the following code (note that it's an endless loop — you'll likely want to plug-in your program termination check as the condition to while()):
while( true ) {
try {
sem.tryAcquire( 10, TimeUnit.SECONDS );
} catch( InterruptedException e ) {
continue;
}
runTask();
sem.drainPermits();
}
Then, in order to trigger immediate execution, the client thread needs to do:
sem.release();
Thus, the server thread will execute the task upon either acquiring a permit from the semaphore as soon as a client thread releases one (triggered immediate execution,) or timing-out in Semaphore.tryAcquire() (periodic executions 10s apart, end-to-start.) Having executions 10s apart start-to-start will take some slightly more involved logic, as well as keeping track of last execution's starting time, but the basic idea remains the same.
You need to drain the permits each time in order to avoid multiple back-to-back executions of the task, in cases where it might be triggered for immediate execution while still being executed.

Interrupt Thread in java

I have a situation where I'm using a Thread, she call a method that will do multiple processes, I need to use a "cancel" button in which you have to stop the thread, I not can use: "while" ,to verify that it was canceled because it not has loop in this process.
Ex:
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
controller = new FirstEtapaController();
execProcess();
return null;
}
};
new Thread(task).start();
Call Method
private void execProcess() {
Thread thread = new Thread(new Runnable() {
public void run() {
getController().execMhetod();
refreshTable();
}
});
thread.start();
thread.join();
};
Ie, I need to stop this process, even when the "ExecMethod" already running, it will take minutes, so I've gotta stop it and not have to wait for him to finish so that , others do not continues.
Remembering that this process will do iteration with my DAO.
The only way (well behaved way) is to add logic points in you spawned threads to check for an interrupted state. You can choose to use the built-in Thread.interrupt() mechanisms, or add your own logic using some form of thread-safe variable (an AtomicBoolean?) or a Semaphore of some sort.
If you use the Thread.interrupt() then your child processes will throw an InterruptedException when they encounter certain conditions, like Thread.wait() and other methods which require synchronization or use the java.util.concurrent.* classes.
You will need to (should already be) handle the InterruptedExceptions in the threads anyway, but perhaps you will need to put regular 'checks' in your child processes to look for the interrupted state anyway (can use Thread.isInterrupted() )
It is worth reading this Handling InterruptedException in Java
If instead of a raw Thread if you use an ExecutorService you'll end up with lots of additional methods/levers to control your threads, one of which is shutdownAll() which uses Thread.interrupt() to kill your thread and lets you check thread status via isTerminated()
Your user interface does not have to wait for the worker thread to finish, so don't worry too much about that.
Alas, Thread.destroy() and Thread.stop() are deprecated, due to bad implementations. I don't think there is a good "sig-kill" type of substitute for Java threads. You are going to have to recode the worker to check an abort flag of some kind, if it matters much. Otherwise, just let it waste a little CPU. ("you can't cancel that Save -- I've already done it!", in effect)
Whether or not a task can be canceled really depends on its implementation. Typically it intermittently checks a flag whether it should continue or not.
You can implement such a flag yourself, and a method to set it :
private volatile boolean shouldStop;
public void cancel() {
shouldStop = true;
}
#Override
public void run() {
while (!shouldStop) {
// do work
}
}
But threads already come with a flag : the interrupted flag. And while it is not necessarily used for canceling a thread, it is typical to use it for exactly that purpose. In fact the standard ExecutorService implementations will try to cancel their threads by interrupting them.
Aside from that several blocking methods (methods that put a thread in BLOCKED or WAITING state) will throw an InterruptedException when the thread is interrupted, at which point they become RUNNABLE again. This is something the previous approach with a boolean flag cannot achieve.
Therefore it is a better approach to use interruption to allow a task to be canceled. And you do not really need that cancel() method any more either :
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// do work
}
}
As a bonus, any code that knows your thread, knows how to cancel it. Including standard ExecutorService implementations.
Care should be taken when catching an InterruptedException, since doing that clears the interrupted flag. It is adviseable to always restore the interrupted flag when catching the Exception, so clients also know it's time to stop doing what they're doing.
private BlockingQueue<Integer> queue;
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Integer id = queue.take(); // blocking method
// do work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
To cancel a thread, you can simply keep a reference to the Thread object and call interrupt() on it :
Thread thread = new Thread(new InterruptibleTask());
thread.start();
// some time after :
thread.interrupt();
But a more elegant approach is keeping tabs on your task (and not so much the specific thread it runs on) through a Future object. You can do this by wrapping your Runnable or Callable in a FutureTask.
RunnableFuture<Void> task = new FutureTask<>(new InterruptibleTask(), null);
new Thread(task).start();
// some time after :
task.cancel(true); // true indicating interruption may be used to cancel.
A Future is key in controlling your task. It allows you to wait for its completion, and optionally receive a value the task calculated :
try {
String value = future.get(); // return value is generically typed String is just as example.
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // since future.get() blocks
} catch (ExecutionException e) {
logger.log(Level.SEVERE, "Exception on worker thread", e.getCause()); // the ExecutionException's cause is the Exception that occurred in the Task
}
If you have several tasks (or even just one) it is worth using an ExecutorService :
ExecutorService pool = Executors.newCachedThreadPool();
Future<?> submit = pool.submit(new InterruptibleTask());
pool.shutdownNow(); // depending on ExecutorService implementation this will cancel all tasks for you, the ones Executors returns do.

Prevent multiple asynchronous calls from being in flight simultaneously without blocking

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.

Implement timeout in Java 1.4

I can not use Executor and Future for trapping TimeOutException as it is 1.4
I need to timeout after 30 seconds if method is not complete.
//Caller class
public static void main() {
EJBMethod() // has to timeout after 30 seconds
}
//EJB method in some other class
public void EJBMethod() {
}
An approach that I am thinking is to wrap this method call in a Runnable and set some volatile boolean from run() after method is over. THen , in caller, we can sleep for 30 seconds after calling that method and once woke up, I will check the boolean in caller if it is SET. If not set, then we need to stop that thread.
In the simplest case, you could just go with a Thread + an arbitrary Runnable.
If you want to make the call blocking from the perspective of the caller, you can create a "service" class that runs a worker thread and uses Thread.join(long) to wait for the operation to complete or abandon it after the specified timeout (Pay special attention to the proper handling of InterruptedException so things don't get messed up).
Thread.isAlive() will tell you whether the Thread finished or not.
Retrieving the result is a separate concern; I guess you can deal with that...
[EDIT]
Quick-and-dirty example (do not use in production as is!):
/**
* Actually needs some refactoring
* Also, did not verify for atomicity - should be redesigned
*/
public V theServiceCall(final T param) {
final MyResultBuffer<V> buffer = new MyResultBuffer<V>();
Runnable task = new Runnable() {
public void run() {
V result = ejb.process(param);
buffer.putResult(result);
}
}
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
try {
t.join(TASK_TIMEOUT_MILLIS);
} catch (InterruptedException e) {
// Handle it as needed (current thread is probably asked to terminate)
}
return (t.isAlive()) ? null : buffer.getResult();
}
NOTE: Instead of Thread.setDaemon() you can implement a shutdown flag in your Runnable as it would be a better solution.
[/EDIT]

Why does the thread started by ScheduledExecutorService.schedule() never terminate?

When I create a thread by calling ScheduledExecutorService.schedule(), it never terminates after executing the scheduled task.
For example the following program never quits:
public static void main(String[] args) {
ScheduledFuture scheduledFuture =
Executors.newSingleThreadScheduledExecutor().schedule(new Callable() {
public Void call() {
doSomething();
return null;
}
}, 1, TimeUnit.SECONDS);
}
public static void doSomething() {
}
Is this a JDK bug, or did I just miss something?
A scheduled task is either being executed or is waiting to be executed.
If the task is waiting to be executed, future.cancel() will prevent it from being executed (both cancel(true)/cancel(false)).
If the task is already being executed, future.cancel(false) will have no effect. future.cancel(true) will interrupt the thread that is executing that task. Whether this will have any effect is up to you, who will implement that task. A task may or may not respond to interruption depending on the implementation.
In order to make your task responsive to cancellation, you must implement doSomething() so that it will respond to interruption.
There are basically two way to do this:
1.Check interruption flag in your logic
public void doSomething(){
stuff();
//Don't use Thread.interrupt()
if(Thread.currentThread().isInterrupted()){
// We have an interruption request, possibly a cancel request
//Stop doing what you are doing and terminate.
return;
}
doLongRunningStuff();
}
You must occasionally check for the interruption flag, and if interrupted, stop what you are doing and return. Be sure to use Thread.isInterrupted() and not Thread.interrupt() for the check.
2.Act upon Interrupted exception
public void doSomething(){
try{
stuff();
}catch(InterruptedException e){
// We have an interruption request, possibly a cancel request
// First, preserve Interrupted Status because InterruptedException clears the
// interrupted flag
Thread.currentThread.interrupt();
// Now stop doing your task and terminate
return;
}
doLongRunningStuff();
}
When you have any method that throws InterruptedException, be sure to stop what you doing and terminate when one is thrown.
Once you implement your methods in this way, you can call future.cancel(true) to cancel the execution of a running task.
Your program never terminates because you create a ScheduledExecutorService, which holds a thread pool, but you never shut down the service. Therefore, the user threads in the thread pool are never terminated, and hence the VM keeps running forever.
To solve this problem, you need to call a shutdown() on the executor service. This can even be done directly after scheduling the task you want to execute:
public static void main(String[] args) {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture scheduledFuture = executorService.schedule(new Callable() {
public Void call() {
doSomething();
return null;
}
}, 1, TimeUnit.SECONDS);
executorService.shutdown();
}
This will execute the scheduled task normally and then terminate the thread in the pool.
You need to call scheduledExecutorService.shutdown() to stop the execution. Otherwise it is restarted every second.
(EDITED: see comments)

Categories

Resources