Does the thread continue running when Future.get(timeout) timeouts - java

As the title showed, If Future.get(timeout) timeout, does the thread continue running,
ExecutorService executor = Executors.newFixedThreadPool(n);
Callable<Object> task = new Callable<Object>() {
public Object call() {
//...
}
}
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
// handle the timeout
}
If the thread continue to run and get blocked due to some IO, etc, then when the threadpool get full, not new task can be sumitted, which means the trheadpool gets stuck, since all the threads in the pool are blocked, right?

The call to future.get(..) will block the thread running it for up to 5 seconds. The task executed by the thread pool will be unaffected, and will continue running until a graceful termination / exception / interruption.
Regarding the submission of new tasks when the thread pool is in full capacity, in your case the tasks WILL be submitted (releasing the submitter thread immediately), but will wait in the thread pool queue for execution. The API documentation of Executors.newFixedThreadPool(..) specifies this clearly.

Right, underlaying thread will be live until IO thrown an exception or ended.

Related

multithread: java condition await timeout but can't return

Lock sharedLock = new ReentrantLock();
Condition condition = lock.newCondition();
main thread:
sharedLock.lock();
childThread.start();
condition.await(5, TimeUnit.SECONDS);
sharedLock.unlock();
child thread:
sharedLock.lock();
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
condition.signal();
sharedLock.unlock();
Suppose child thread send a network request and wait for response, I want main thread wait at most 5 seconds, if timeout, retry the request. but when the await() timeout, it cannot acquire lock because child thread still hold it, so it still wait the lock until child thread release it, which takes 10 seconds.
How can I achieve my requirement that main thread wait child thread's signal, but have a bounded timeout?
This is not how your are supposed to do it, you are supposed to:
Create an ExecutorService (thread pool) for that you should check the methods of the class Executors to choose the best one in your case but Executors.newFixedThreadPool is a good start
Submit your task as a FutureTask to the thread pool
Then call get with a timeout
Manage properly the TimeoutException
Here is how it could be done:
// Total tries
int tries = 3;
// Current total of tries
int tryCount = 1;
do {
// My fake task to execute asynchronously
FutureTask<Void> task = new FutureTask<>(
() -> {
Thread.sleep(2000);
return null;
}
);
// Submit the task to the thread pool
executor.submit(task);
try {
// Wait for a result during at most 1 second
task.get(1, TimeUnit.SECONDS);
// I could get the result so I break the loop
break;
} catch (TimeoutException e) {
// The timeout has been reached
if (tryCount++ == tries) {
// Already tried the max allowed so we throw an exception
throw new RuntimeException(
String.format("Could execute the task after %d tries", tries),
e
);
}
}
} while (true);
How can I achieve my requirement that main thread wait child thread's
signal, but have a bounded timeout?
Here is how you can achieve your requirements:
Main Thread:
lock.lock();
try {
childThread.start();
condition.await(5, TimeUnit.SECONDS);
} finally {
sharedLock.lock();
}
The child thread:
try {
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
} finally {
// Here we notify the main thread that the task is complete whatever
// the task failed or not
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}
As you can see to work, the task must not be performed within the critical section, we only acquire the lock to notify the main thread nothing more. Otherwise if you execute the task within the critical section after the timeout the main thread will still need to acquire the lock once again and since the lock is actually owned by the child thread, it will need to wait anyway until the end of the task which makes the timeout totally useless.
NB: I renamed sharedLock to lock as a ReentrantLock is an exclusive lock not as shared lock, if you need a shared lock check the class Semaphore to define the total amount of permits.
Your code can be simplified with intrinsic lock.
Object sharedObj = new Object();
main thread:
synchronized (sharedObj) {
int retryCount = 0;
while (retryCount < maxRetry) {
sharedObj.wait(5000);
retryCount++;
}
}
child thread:
synchronized (sharedObj) {
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
sharedObj.notify();
}
java condition await timeout but can't return
That's because the lock must be released so wait/await can return. So your child thread should be like:
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
synchronized (sharedObj) {
sharedObj.notify();
}
Java's wait/notify is usually used to solve producer-consumer problem. And usually sharedObj shouldn't be holded for too long. Then your main thread can hold the lock again when the wait timeout.
Take a look at an in-production example: hadoop/hdfs/DFSOutputStream.java
The logic is simple, the producer creates packet and put it in dataQueue
// takes a long time to create packet
synchronized (dataQueue) {
dataQueue.addLast(packet);
dataQueue.notifyAll();
}
The consumer wait while dataQueue is empty:
synchronized (dataQueue) {
while ((!shouldStop() && dataQueue.size() == 0 &&... ) {
try {
dataQueue.wait(timeout);
} catch (InterruptedException e) {
LOG.warn("Caught exception", e);
}
doSleep = false;
now = Time.monotonicNow();
}
As you can see, the dataQueue are unlocked for most of the time!
How can I achieve my requirement that main thread wait child thread's signal, but have a bounded timeout?
If your child thread are mostly in a loop, your Main thread can set a isRunning flag to make child thread stop by itself. If your child thread are mostly blocking by an I/O operation, your Main thread can interrupt the child thread.
The sharedObj is used for coordination and protects sharedObj. If there's other resources should be protected, you have 2 choices:
1. If the operation on the resource is quick, like ackQueue in DFSOutputStream.java, protect it together inside the sharedObj.
2. If the operation on the resource is time-consuming, do it and protect it outside the sharedObj.
The valid confusion in the question is because the "Thread.sleep(10)" is done inside the lock block. When await(long time, TimeUnit unit) has to return because of timeout, it still needs the lock. So, as suggested in the other answer the long running task should not be inside the lock for it to work properly.
But it would be nice to have proper documentation stressing this fact. For example, if we await(5, TimeUnit.SECONDS) i.e wait for 5 seconds and the lock is available 10 seconds after the call, it will still return false even though the lock is available now at the moment of return.

Properly shut down ThreadPoolExecutors

I'm new to java concurrency an would like to ask the following basic question. I'm creating a ThreadPoolExecutor for imporving performance as follows:
int n = Runtime.getRuntime().availableProcessors()
ExecutorService executor = Executors.newFixedThreadPool(n);
for( int i = 0; i < n; i++)
executor.execute(new Work());
After all thread in the thread pool have finished their tasks I need to shutdown the pool properly. I would tried this:
while(true){
if(executor.isTerminated()){
executor.shutdownNow();
break;
}
}
But I'm not sure about that because I think we waste a lot of processors resources to queriyng the executor for termination.
What is the right solution for that?
UPD: Runnable task:
public class Work implements Runnable{
private String sql;
public Work() {
//init sql
}
#Override
public void run() {
JdbcTemplate template = new JdbcTemplate(dataSource);
#SuppressWarnings("unchecked")
List<Integer> ints = template.queryForList(sql, Integer.class);
//Storing the list into a global cache
}
}
There seems to be something mystical around shutting down an ExecutorService.
From the documentation of shutdown():
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
So all you have to do is to invoke shutdown() after you have submitted all your tasks, the exact time doesn’t matter. They don’t have to be completed at that time. The ThreadPoolExecutor will finish all tasks and then clean up all resources.
And it will do so regardless of whether you wait for it or not. So you don’t need to wait, just invoke shutdown() when you are confident that you will not submit new tasks, the rest will happen as soon as possible.
It says:
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.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
So use awaitTermination instead. And for threads that take time, use a boolean variable as volatile and check it if it is set outside.If set then exit etc. something like that
try {
executor = Executors.newSingleThreadExecutor();
future = executor.submit(task);
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
finally {
if (Objects.nonNull(executor) && !executor.isTerminated()) {
LOGGER.error("cancelling all non-finished tasks");
}
if (Objects.nonNull(executor)) {
executor.shutdownNow();
LOGGER.info("shutdown finished");
}
}
This way you shutdown executor and waiting for 5 seconds to complete all tasks and then finally calling executor.shutdownNow() to completely kill the executor.
This is the best way to shutdown executor.

ExecutorService#awaitTermination blocks forever - broken / special on GAE?

GAE just blocks forever when I try to terminate an ExecutorService. Small sample below:
ThreadFactory threadFactory = ThreadManager.currentRequestThreadFactory();
ExecutorService pool = Executors.newSingleThreadExecutor(threadFactory);
Future<String> future = pool.submit(new Callable<String>() {
public String call() throws Exception {
return "Hello from Thread";
}
});
LOG.info("Result is: [" + future.get() + "]. Pool expected to be idle now");
pool.shutdown();
if (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
LOG.info("Pool does not like shutdown()");
pool.shutdownNow();
if (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
LOG.info("Pool does not even like shutdownNow()");
}
}
The same code works without blocking when running locally, it just blocks without terminating when running deployed on AppEngine. The timeout can be increased until the 60 second request limit forces the code to interrupt.
This seems to be a subtle yet dangerous difference to a standard JVM. Code found regularly to clean up can essentially kill your service. ThreadManager documentation mentions that the threads are a bit special but they are -as far as I understand - interruptible and meant to terminate.
Is it just me (some library messing with threads)?
Is it a bug / feature / somewhere documented?
Since waiting for termination is just pointless, is it okay to just call pool.shutdown(), then assume all is going to be okay? Running threads are a good way to leak memory..
Update #1
I'm even more confused after some more testing. All works fine when using a Thread directly. Slightly convoluted example:
final CountDownLatch threadEnter = new CountDownLatch(1);
final Object wait4Interrupt = new Object();
Runnable task = new Runnable() {
public void run() {
synchronized (wait4Interrupt) {
threadEnter.countDown();
try {
wait4Interrupt.wait();
} catch (InterruptedException e) {
// expected to happen since nothing is going to notify()
LOG.info("Thread got interrupted.");
Thread.currentThread().interrupt();
}
}
}
};
Thread thread = ThreadManager.createThreadForCurrentRequest(task);
// not started state
LOG.info("Thread log #1: " + thread + " " + thread.getState());
thread.start();
threadEnter.await();
// thread is inside synchronized / already waiting
synchronized (wait4Interrupt) {
// => guaranteed that thread is in waiting state here
LOG.info("Thread log #2: " + thread + " " + thread.getState());
thread.interrupt();
}
thread.join(1000);
// thread is dead
LOG.info("Thread log #3: " + thread + " " + thread.getState());
Logs produced:
I 16:08:37.213 Thread log #1: Thread[Thread-7,5,Request #0] NEW
I 16:08:37.216 Thread log #2: Thread[Thread-7,5,Request #0] WAITING
I 16:08:37.216 Thread got interrupted.
I 16:08:37.217 Thread log #3: Thread[Thread-7,5,] TERMINATED
The thread returned by the factory isn't started, it supports wait & interrupt just fine and it can be join()'d and is terminated afterwards. What else would an ExecutorService want to do?
Update #2
pool.toString() from example #1 after shutdown() results in
java.util.concurrent.ThreadPoolExecutor#175434a
[Shutting down, pool size = 1, active threads = 0, queued tasks = 0, completed tasks = 1]
which also indicates that it's not an issue caused by unterminated threads since it states active threads = 0.
Update #3
Pools do shutdown nicely when being told to do so before they finished their task. The following terminates correctly after 500 ms. Adding future.get() will show the original problem again.
Future<String> future = pool.submit(new Callable<String>() {
public String call() throws Exception {
// sleep a bit so pool is "busy" when we're trying to shutdown.
Thread.sleep(500);
return "Hello from Thread";
}
});
// get here = evil
pool.shutdown();
pool.awaitTermination(2, TimeUnit.SECONDS);
=> Issue seems to occur on idle pools only. Busy pool can be shutdown.
You are right, Threads on App Engine are interruptible. Quoting from the official docs:
An application can perform operations against the current thread, such as thread.interrupt().
Since it is working fine locally, it is a difference between the development server and the sandbox at production environment.
I think the development server allows multi-threaded execution if not disabled while the production environment requires to explicitly state it in the application config file (appengine-web.xml):
<threadsafe>true</threadsafe>
Unless you explicitly state your app is thread-safe, serving a request can only use 1 thread therefore your ExecutorService cannot start a new Thread to execute the task you submitted and therefore future.get() will block. It would block until the "current" thread would end but obviously that could only happen after serving the request, so you have a deadlock here.

Do i need to use threadPool.awaitTermination after future.get();

I am using the ExecutorService to create a Thread Pool. After adding all tasks, the threadPool is shutdown.
Now the Java Doc for Future.get() says
Waits if necessary for the computation to complete, and then retrieves its result.
I am not able to understand the "if necessary" part. When does the future.get() method wait and how much time will it wait?
If it waits till the thread execution is over, is there a need threadPool.awaitTermination?
ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads);
List<Future<?>> futureObjList = new ArrayList<Future<?>>();
for (int i = 0; i < numberOfThreads; i++) {
...
Future<?> future = threadPool.submit(myThread);
futureObjList.add(future);
...
}
threadPool.shutdown();
for(Future<?> future : futureObjList){
try {
future.get();
} catch (Exception e1) {
//if any thread fails, all other thread should stop their execution.
threadPool.shutdownNow();
}
}
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e1) {
throw e1;
}
The "if necessary" just means that the get() method might block or not depending if the thing that is happening in the Runnable or Callable is already done or not.
Suppose you submit a Callable to an executor service. The Callable takes 2 seconds to execute.
If you call get() 1 second after the submit, the get() will block for 1 more second. However, if you would have called get() 5 seconds after the submit, the get() would not block and immediately return.
future.get()
will block calling thread, if method .call of Callable haven't returned a result by the time .get is invoked. If you iterate over every future, then by the time you exit a for-loop, all threads have finished executing.
You will have to call threadPool.awaitTermination() before getting the results from the threads as awaitTermination will wait for all the threads to complete computation. After all threads have completed you can be sure that future.get() will not block as it has completed its execution. future.get() will wait until the thread finishes execution unless you specify a timeout.

Java: Set timeout for threads in a ThreadPool

I want to set timeouts for threads which are executed within a thread pool. At the moment I have following code:
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
The code just splits a big list of objects into sublists and process these sublist within single threads. But this is not the point.
I want to give each single thread in the thread pool a timeout. For only one thread in the pool I found following solution:
Future<?> future = null;
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
future = executor.submit(worker);
}
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
}
But this would not work for more than one thread. Maybe I have to put each thread in a List<Future> list and iterate over this list and set a timeout for each future object?
Any suggestions?
EDIT AFTER USING CountDownLatch:
CountDownLatch doneSignal = new CountDownLatch(partition.size());
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newFixedThreadPool(8);
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
tasks.add(executor.submit(doneSignal, worker));
}
doneSignal.await(1, TimeUnit.SECONDS);
if (doneSignal.getCount() > 0) {
for (Future<?> fut : tasks) {
if (!fut.isDone()) {
System.out.println("Task " + fut + " has not finshed!");
//fut.cancel(true) Maybe we can interrupt a thread this way?!
}
}
}
Works good so far.
So next question is how to interrupt a thread which is timed out? I try fut.cancel(true) and add following construct in some critical loops in the worker thread:
if(Thread.interrupted()) {
System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!");
return;
}
So the worker thread is "killed" after the timeout. Is this a good solution?
Furthermore: Is it possible to get the name of the thread which timed out over the Future interface? At the moment I have to print out the name in the if condition of the Thread.interrupted() construct.
Thanks for help!
Regards
Have you seen this? ExecutorService.invokeAll
It should be exactly what you want: Invoke a bundle of workers and have them timeout if taking too long.
EDIT after comment - (new idea):
You can use a CountDownLatch to wait for the tasks to finish AND timeout via await(long timeout, TimeUnit unit)!
You can then even do a shutdownNow and see which tasks have taken too long ...
EDIT 2:
To make it clearer:
Have a CountDownLatch be count down by each Worker, when finished.
In the main execution thread await with timeout on said latch.
When that call returns, you can check the Latches's count to see if there has been the timeout hit (if it is >0).
a) count = 0, all tasks finished in time.
b) if not, loop the Futures and check their isDone. You don't have to call shutdown on the ExecutorService.
Call shutdown if you do not need the Executor any longer.
Note: Workers can finish in the meantime between the timeout and calling their Future's isDone().
Future future = executorService.submit(callable)
future.get(timeout, unit)
For more information see this link.

Categories