I am trying to implement timeout for a thread which is invoked asynchronously by executor.
Process flow is like below:
Thread-1: Initiates a task to run on thread-2 using below code and returns immediately without waiting for Future object result
Thread-2: Long process and wil update some store some result in cache at end
Now, the requirement is to kill Thread-2 after some timeout value without blocking Thread-1
code snippet:
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Task> future = executor.submit(new Callable<Task>() {
public Task call() throws Exception {
try{
return new Task();
}catch (Exception e) {
//print stack
}
}
});
Any insight/suggestions to implement this?
See the following answer: https://stackoverflow.com/a/2733370/1299078
But depending on what Thread-2 does, you could let the thread end regularly, i.e. define a timeout on a http-request or a DB statement or if you have a loop, define an exit condition. this way you may end up with a more proper solution and you are able to properly release resources.
You can't do it using Java's ExecutorService because it doesn't expose any method to timeout and kill/complete/finish the newly spawned thread.
However, if you must do it then you can do it by directly using Thread class, below is high level approach:
From your main thread t1, spawn your worker thread t2 which is supposed to do your long work.
In your t1, you will have hold of the t2's ORV, pass it a new thread t3 along with time after which you want t2 to finish.
In t3 (you can also do this in t1 if you wish, but since you do not wish to block t1 so you need to have another thread to do this job), once that time has elapsed call t2.interrupt(), this will basically interrupt the t2 thread.
Now in t2, you will have to periodically keep on checking whether the thread is interrupted or not (using if (Thread.interrupted()) {) and if it is interrupted then you can do whatever you want to do like - simply return therefore completing/killing/finishing the thread.
The basic ExecutorService does not provide a timeout functionality.
You could implement the timeout yourself like described by #hagrawal or you can use guava which has a very nice implementation for what you're asking for here
Related
In the book Effective Java by Joshua Bloch, there is this example (item 81):
// Simple framework for timing concurrent execution
public static long time(Executor executor, int concurrency,
Runnable action) throws InterruptedException {
CountDownLatch ready = new CountDownLatch(concurrency);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch done = new CountDownLatch(concurrency);
for (int i = 0; i < concurrency; i++) {
executor.execute(() -> {
ready.countDown(); // Tell timer we're ready
try {
start.await(); // Wait till peers are ready
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.countDown(); // Tell timer we're done
}
});
}
ready.await(); // Wait for all workers to be ready
long startNanos = System.nanoTime();
start.countDown(); // And they're off!
done.await(); // Wait for all workers to finish
return System.nanoTime() - startNanos;
}
It then says:
The executor passed to the time method must
allow for the creation of at least as many threads as the given concurrency level, or
the test will never complete. This is known as a thread starvation deadlock
[Goetz06, 8.1.1].
I am not sure why this would deadlock, e.g. with 1 one thread and two tasks. Do you have an example of a way it could deadlock?
TL;DR : The concurrency variable specifies the number of tasks to be executed by the threads in the Executor thread pool passed as parameter of the method time. A deadlock occurs if those tasks are not executed by different threads.
From the CountDownLatch documentation one can read:
A CountDownLatch is initialized with a given count. The await methods
block until the current count reaches zero due to invocations of the
countDown() method, after which all waiting threads are released and
any subsequent invocations of await return immediately.
Equipped with this information, let us imagining that each task is indeed be executed by a different thread. So each thread used from the Executor to run the parallel work:
() -> {
ready.countDown(); // Tell timer we're ready
try {
start.await(); // Wait till peers are ready
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.countDown(); // Tell timer we're done
}
}
will call first:
ready.countDown();
and then wait in start.await(); for the master thread to call start.countDown(); (which is the only thread doing it). However, before doing so, the master thread is waiting on:
ready.await();
for the remains threads to call ready.countDown(); concurrency times. So that the master thread can resume its work. Therefore, if each of those tasks are not executed by concurrency separate threads, those threads will wait for the master thread that in turn is waiting for them as well, hence a deadlock and the statement:
The executor passed to the time method must allow for the creation of
at least as many threads as the given concurrency level, or the test
will never complete.
So regarding your question:
I am not sure why this would deadlock, e.g. with 1 one thread and two
tasks. Do you have an example of a way it could deadlock?
So let us say that concurrency=2, and you have a thread on the Executor pool and the master thread. The master thread calls:
ready.await();
which was initialized as follows:
CountDownLatch ready = new CountDownLatch(concurrency);
therefore ready.countDown(); needs to be called at least twice. However, there is only one thread on the Executor pool that calls ready.countDown(); only once and then waits at:
start.await();
for the master thread to call start.countDown();, but that thread is still waiting on ready.await();. So both threads are waiting on each other, which leads to a deadlock.
A simple invocation that would deadlock:
time(Executors.newFixedThreadPool(1), 2, () -> System.out.println("Hello world"));
Here, an executor with just 1 thread is passed in. Since concurrency is 2, the one thread waits on the "Tell timer we're ready" line for another thread to decrease the counter again.
But there is no other thread to decrease the counter, because there's only one thread. So the only thread is blocked waiting.
i have found that isAlive() method is not working when executing a thread using ExecuterService.
And interrupt() and stop() method is also not working.
The code i used:
Thread t1=new Thread(()->{
try{
Thread.sleep(10000);
} catch(InterruptedExeception ie){
System.out.println("Interrupted");
}
Thread.sleep(5000);
System.out.println("It's Done");
});
ExecuterService excuter=Executers.newSingleThreadExecuter();
excuter.execute(t1);
Thread.sleep(2000);
System.out.println(t1.isAlive());
Thread.sleep(2000);
t1.interrupt();
t1.stop();
My expected output is :
true
Interrupted
Actual output is :
false
It's Done
I need reason for this behavior. And I want to know what is the solution for the problem and how I use these methods when a Thread is running inside a ThreadPool.
The stop() method does not work. You can't stop threads like this. A thread needs to opt into allowing itself to be stopped; you'd for example update a (volatile, or AtomicBoolean-style) boolean, and the thread runs a loop, and on each loop, checks that boolean; if it's false, it ends. There is no way to stop arbitrary threads in their tracks. At all. You can google for information about why Thread.stop is deprecated (and effectively doesn't work at all anymore, even though the method is still around, primarily as vehicle for the documentation on why you can't do that anymore).
Threads implement runnable, which is why you're even allowed to pass that thread to the executor method, but the entire thread infra isn't being used at all. You should update this code to be Runnable r = () -> { ... } and pass that. Your code as written is misleading you into thinking that's the thread that is being run. It's not, which is why you're getting false for .isAlive().
Executors as a rule don't expose the way they do the job, they just do it. If you want to check if the job is running, set a (volatile, or AtomicBoolean) boolean to true upon entry, and to false upon exit. Alternatively, don't bother with an executor service, just start your thread, if you really want to use thread functionalities such as .isAlive().
t1 is not a thread.
t1 is a Thread instance, but a Thread instance is not the same thing as a thread, and the way you are using t1, no thread is ever created. Think of a Thread instance as a handle that you use to create and control a thread. The thread would be created if your program called t1.start(), and then the t1.isAlive() and t1.interrupt() and t1.stop() calls all would operate on that new thread.
Besides being a Thread instance, t1 also happens to be a Runnable instance, which is what the executer.execute(...) call wants. Being a Runnable just means that t1 has a run() method. There are various ways that run() method could be called:
You could start the thread, t1.start(), in which case, the new thread would call it,
You could (you did) give it to an Executor. When you do that, the Executor arranges to have one of its worker threads call your run() method.
You could simply call it -- t1.run() -- which is no different from calling any other method that your code defines.
You could pass it to any other library method that wants a Runnable. (I don't know how many there are, maybe a lot.)
If you want t1.run() to be called in a thread that your code can control, then call t1.start() to create that thread. If you want it to be called by an executor service, whose threads you should not attempt to control, then do what you did: call excuter.execute(t1);
Just don't do both. That probably isn't what you want.
P.S., If you want to continue using the Executor service, then you probably should change your declaration of t1. Since it only needs to be a Runnable in that case, you can write:
Thread t1=new Runnable(()->{
...
});
That way, people reading your code won't scratch their heads and wonder whether you knew what you were doing.
Having an ArrayList<Wheel> wheels, being Wheel a class that extends Thread, what happens if I have the follow:
wheels.forEach(a -> {
try{
a.interrupt();
a.join();
}catch(InterruptedException exception){}
});
What will be the instruction order from this code?
Right now I think it will go the following: 1)a is interrupted, 2)my main thread will join a, and ONLY AFTER a being finished will the forEach loop continue thru the remaing of the items, right?
Is it possible to do an iteration in the ArrayList where all the threads in it will be interrupted and joined, without doing it item by item manually?
Thank you very much for the help!
Johnny's comment is correct for your current implementation. You could also follow another path like;
Instead of extending thread, you can implement Runnable(or Callable) in your Wheel class and submit your list of tasks to a executor service. This way you can get the benefits of thread pooling(reusing threads) and use the built in functionality of shutting down and waiting all threads to complete.
Example:
ExecutorService executor = Executors.newFixedThreadPool(5);
wheels.foreach(wheel -> executor.submit(wheel));
//when you want to shutdown
executor.shutdownNow(); // this will send interrupt to thread pool threads.
executor.awaitTermination(10, TimeUnit.SECONDS);
// block the current thread until executor finishes or timeout expires.
// You could give a bigger timeout or call this with in a while loop to ensure
// executor definitely finished.
// like this: while(!executor.awaitTermination(10, TimeUnit.SECONDS));
I want to stop / kill all Threads (Runnables) started by Main after a given timeout. I tried to do as mentioned below. But it is not working as expected. Apart from that, I tried with the Thread.interrupt() but the results is negative. I tried thread.stop(). It is working but deprecated.
Can anyone give some idea on this?
Note : I'm focusing on a solution for Runnables not Callables. And I'm trying to do this bymodifying only the client code (Main). Not the Threads (Supplier)
Main
Thread roxtoursThrd = new Thread(new Supplier("roxtours", 1));
Thread bluevacationsThrd = new Thread(new Supplier("bluevacations", 1));
Thread elixerThrd = new Thread(new Supplier("elixer", 1));
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
taskExecutor.execute(roxtoursThrd);
taskExecutor.execute(bluevacationsThrd);
taskExecutor.execute(elixerThrd);
taskExecutor.shutdown();
// taskExecutor.shutdownNow(); // This is also not stopping threads. They continue.
try {
taskExecutor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
Supplier.java
public class Supplier implements Runnable {
public Supplier(String name, int count) {
this.name = name;
this.count = count;
}
#Override
public void run() {
try {
// Some time consuming operations (URL Connections, XML Decoding, DB Queries etc etc) are goes in here.
} catch (Exception e) {
e.printStackTrace();
}
}
String name = null;
int count = 0;
Logger logger = Logger.getLogger(Supplier.class);
}
Making the executor's tasks respond to interruption will require changing the code for the Suppliers. Interruption is cooperative; the thread being interrupted gets a flag set on it, but it's up to the thread to decide how to handle it. If your Runnable doesn't act on it, as in your example, then nothing happens, the thread just keeps on executing.
The Executor can only cancel threads that respond to interruption, see the API documentation for ExecutorService.shutdownNow:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
A thread can check its flag with the Thread#isInterrupted method. Your Runnable task should check Thread.getCurrentThread().isInterrupted().
If a thread is waiting or sleeping when the interrupted flag is set then an InterruptedException will be thrown and the flag will be cleared.
Do not use Thread#setDaemon(true) unless you're prepared for those threads to disappear suddenly with no warning and no chance to clean up pending tasks when the rest of the application shuts down.
The other option is the deprecated Thread#stop method, which causes ThreadDeath to be thrown. Unlike interruption, this is not cooperative, and it's between difficult and impossible to write code that can predictably and cleanly terminate when this exception occurs, because ThreadDeath can be thrown anywhere, unlike InterruptedException, which is much more manageable since it is only thrown from specific blocking calls.
Use shutdownNow() instead of shutdown().
The shutdown() will initiate the shutdown and it will not accept any new tasks but you never know when the threads will be actually stopped.
The shutdownNow() will immediately attempts to stop all the active threads and this will return all the active threads which are awaiting for execution.
Again there is no guarantee that all the threads will be stopped immediately (Threads will go for a graceful shutdown and it may take time based on the task given to the thread). We have to use either of the below methods to wait till all the threads are completed its execution.
executor.awaitTermination(...);
or
while (! executor.isTerminated()) {
// Sleep for few milliseconds...
}
Refer the doc: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29
Your thread's run method is not blocking, hence it does not run into a situation where an InterruptedException is thrown.
When a Thread is inerrupted, besides throwing an exception if it is blocking, it also has its interrupted status set, that is to say the method Thread#isInterrupted() returns true. Also, the method Thread#interrupted also returns true, but with the latter the interrupted status of the thread is cleared.
In your example you are not blocking nor are you checking the threads inerrupted status.
EDIT: Since you are not checking to see if the thread is interupted nor are you blocking, then you can't stop the threads explicitly, but you can stop them by making them daemon threads and then when your main thread (which is a user thread) finishes, all the other daemon threads will stop. Main difference between daemon thread and user thread is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish there execution.
If you want to interrupt threads, you have to provide interruption entrance point. Sleep for a very short time, for example, then catch and handle InterruptionException.
Next what you can do is make use of isInterrupted() method in every iteration and the handle that as well.
Other approach would be to make all the threads daemons with setDaemon(), as they would be killed after main thread finishes, but this would be useful only if main was to be stopped.
In response to your edit/updated question:
excerpt from shutdownNow() documentation
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
So either you prepare you application to work as multi-threaded or you stick to single thread.
Also, see How do you kill a thread in Java?.
And the most important link from the question above: http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
I start one thread to download contents from the internet, at one time, the thread is downloading one file, and then i want it stop and begin to download another file, what should i do? should i count on the concurrency mechanism in java?
You can start your thread using a single-thread executor, then when you kill it (gracefully I hope) and start a new one it will ensure that it's using the same thread.
// Suppose you have a DownloadFile class that implements Runnable
DownloadFile task1 = new DownloadFile();
...
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Boolean> future = exec.submit( task1, Boolean.TRUE );
...
// Cancel the task
future.cancel();
// Give the executor another task
DownloadFile task2 = new DownloadFile();
...
exec.submit( task2, Boolean.TRUE );
Other useful docs:
Future
ExecutorService
Stopping thread using stop() method is not recommended.
I start one thread to download
contents from the internet, at one
time, the thread is downloading one
file, and then i want it stop and
begin to download another file, what
should i do?
You need to use the sleep( ) method of Thread class to pause the same thread for some specified milliseconds before you can continue the work with the same thread.
Note : Once the thread has been stopped, it can't resume its work. It will result in IllegalThreadStateException.
See :
Why are Thread.stop() , Thread.suspend() and Thread.resume() Deprecated ?
How to stop a java thread gracefully ?
To interrupt a thread from a current processing and redirect it to something else is a classic synchronization problem. This is done as follows:
Have a job queue. The jobs in the job queue [or more specifically the objects in the job queue] should have a method [say process()] that the thread will execute. The thread generally does not know the details of the process() method. It only cares that it has to run the process() method.
The thread must wait on the job queue. This is done as follows:
Job j = null;
synchronized(jobQueueInstance)
{
if(jobQueueInstance.isEmpty())
{
jobQueueInstance.wait();
}
j = jobQueueInstance.poll(); //get the job from the head of the queue
}
try
{
j.process();
}
catch(InterruptedException ex)
{
//thread is interrupted, means it needs to abandon this job and fetch a new one from the queue
}
I hope this helps. However I have omitted a few things to oversimplify the problem:
I have omitted the Job class declaration, I guess it will either be an interface or an abstract class.
I have also omitted the part where some other thread will add a new Job() and notify() on the jobQueueInstance.
Also omitted the part about the thread that will interrupt() the "busy" job-running thread.
NOTE Threads 3 and 4 can be the same thread.
You should place a timeout on your download using the software for downloading. This usually results in an Exception which you can catch, clean up what you are doing and continue on.
Unless the software you are using supports interrupts or time out settings, there is no safe way to force this to happen externally. You can use stop() safely provided your intention is to shutdown at soon as possible. (In which case System.exit() is a better option)
If you have a library which you have no choice but to kill, you need to run it in a separate process and kill the whole process. This will ensure any resources used will be cleaned up by the OS. (Assuming it hasn't left temporary files etc. ;)