Timeout with CompletableFuture and CountDownLatch - java

I want to wrap a Runnable in CompletableFuture to be computed asynchronously, but with control over when does the computation begin and end. I've created a CompletableFuture with CountDownLatch to block the processing, but the following snippet throws an error:
CountDownLatch countDownLatch = new CountDownLatch(1);
CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop");
});
Thread.sleep(1000L);
System.out.println("Start");
completableFuture.get(1000L, TimeUnit.MILLISECONDS);
countDownLatch.countDown();
Start
Exception in thread "main" java.util.concurrent.TimeoutException
at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at Sandbox.main(Sandbox.java:23)
When I call get without timeout on the other hand, it freezes (only Start is printed).
I expect the runnable in CompletableFuture to run when countDownLatch.countDown(); is called.

You are waiting till the timeout expires without allowing the thread to proceed. The Future.get is blocking and that will never allow you to countDown the Latch before the timeout expires ever, hence your thread never completes. What you have to do here is, first, let the thread proceed by calling the countDown on the Latch and then wait with a timeout in the get call. Just inverting the two lines would solve the issue. Here's how it looks.
countDownLatch.countDown();
completableFuture.get(1000L, TimeUnit.MILLISECONDS);
In fact, if you remove the timeout from the get call (it blocks indefinitely), then this is a typical example of a Deadlock in a system. The worker thread waits until the main thread counts down the latch, while main thread waits for the worker thread to complete so that it can go ahead and countDown the latch. Fortunately, the time out passed to get enables Probabilistic deadlock avoidance. On the contrary, you can cancel the future at any time and avoid potential deadlocks as far as your tasks are responsive to the interruption.

Because of CompletableFuture#get is a blocking call. So, countDownLatch.countDown(); will not execute till the time CompletableFuture#get get the result. CompletableFuture will not complete and return the result as it will wait to countDownLatch to count down. So, basically you have created a dependency between 2 thread such that one will wait for another and vice-versa.

Related

ExecutorService not terminating in time

I have an ExecutorService that runs a few threads.
What I am trying to accomplish is to execute, and then wait for all threads to terminate. To give you more background, every thread1 connects to a website.
This is what I came up with:
public static void terminateExecutor(ExecutorService taskExecutor) {
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("Some tasks were interrupted!"); //This gets printed
}
}
Now, strangely enough, the main thread that uses the ExecutorService terminates, but the thread1s in it don't.
I noticed this because thread1 threw an error (the main thread at this point was already dead) telling me that it didn't find the URL specified (so I guess it's something related to connections).
Is it possible that awaitTermination doesn't terminate the thread1 because its trying (and retrying it seems) to connect to an invalid link?
I cannot stop the thread1 in any other way (or at least to my knowledge I can't), because there isn't any kind of loop.
EDIT:
I get thread1 by creating a new class and feeding it to the executor.
for (....)
{
String urlToVisit = globalUrl + links.get(i);
Thread thread1 = new MagicalThread(urlToVisit, 2).getThread();
executor.execute(thread1);
}
terminateExecutor(executor.getExecutor());
From the Javadoc (emphasis mine):
Blocks until all tasks have completed execution after a shutdown request
You need to call shutdown() before calling awaitTermination, otherwise it does nothing meaningful.
The executor uses interruption to let the threads know it's time to quit. If your tasks are using blocking I/O then they will be blocked and can't check the interrupt flag. There is no ability for the blocked task to respond to the interruption in the way that happens with sleep or wait, where interruption causes the threads to wake up and throw an InterruptedException.
If you set a timeout on the socket then, once the socket times out, the task can check for interruption. Also you can have the task respond to interrupt by closing the socket. See https://www.javaspecialists.eu/archive/Issue056.html
Be aware that implementing this in a threadpool is more involved than in the example given in the linked article. Nothing about the executor lets the pool call methods on a task besides run. One way to do it would be to put a reference to the socket in a ThreadLocal. Then you could make a ThreadFactory for the pool to use to subclass Thread with a method that overrides the interrupt method on the thread to get the socket from the ThreadLocal and close it.
When
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
returns, it doesn't guarantee that the ExecutorService has terminated. Look at its return value:
[Returns] true if this executor terminated and false if the timeout elapsed before termination
You don't check this value, but I'll bet it's returning false if the thing you're running in the ExecutorService is still running.

How to shut down all threads in executor service immidiately?

I have used shutDown() and shutDownNow(), but both method does not stop all threads immediately. shutDownNow() is more preferable among these two but it waits for the running thread to complete it's task. In my scenario I have a huge task dealing with postgres database and I want to shut down that thread immediately without waiting for the completion of execution.
What is the way to shut down the all the threads immediately?
shutdownNow :
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
shutdown :
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29
or you can see this :
You can use an ExecutorService instead which combines a thread pool with a queue of tasks.
ExecutorService service = Executors.newCachedThreadPool();
// or
ExecutorService service = Executors.newFixedThreadPool(THREADS);
// submit as many tasks as you want.
// tasks must honour interrupts to be stopped externally.
Future future = service.submit(new MyRunnable());
// to cancel an individual task
future.cancel(true);
// when finished shutdown
service.shutdown();
The single "clean" way to stop the threads is, if you have some loops inside, to stop the loop through some boolean variable like "stopThread", and you have to handle the variable.
Example:
public void run(){
for(int i=0; i<1000000 && (!stopThread) ; i++){
// do something
}
}
I doubt that it's possible in safe way.
The safe way to shutdown the executor service as per oracle documentation
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
If you really want to follow a crude way, I will suggest a solution which may not be 100% accurate and I don't recommend personally. I would like to use ExecutorService methods instead of this crude solution.
Create your own thread and thread pool as per this article
Add one more boolean in Worker thread - boolean runNow = true;
run method of Worker thread will be like this : while ( runNow) { // your logic }
When you want to shut down all the threads, add one more method in ThreadPoolManager. Iterate through myQueue and interrupt all Runnables. Catch that interrupted exception and make the boolean runNow as false.
Depending on how you call the database, you could try to explicitly cancel the query. Se related question.

ExecutorService - How to wait for completition of all tasks in non-blocking style

I am using ExecutorService in Java web server application for executing some computational tasks in parallel style and then calling shutdown() with awaitTermination() to wait for all tasks to be done. Whole computation can sometimes take dozens of minutes.
The thing is awaitTermination() method blocks the main thread until timeout elapsed (or interrupted) but I just want to start the tasks and immediatedly respond to client and after competition of all tasks shutdown the service (following conventions to always close the thread pool).
So my question, is there a way how I can be notified when all tasks are done so I could call the shutdown() method? Listener or something..
Thanks!
You are trying to solve a problem that doesn’t exist. Consider the documentation of ExecutorService.shutdown():
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. …
This method does not wait for previously submitted tasks to complete execution.
In other words, just calling shutdown() does already everything you want
It finishes all previously submitted tasks
It initiates a shutdown
It does not wait
The only obstacle is that you are calling awaitTermination despite the fact that you don’t want to wait, which has a trivial solution: don’t call awaitTermination.
The confusion arises because in your question you are asking “how I can be notified when all tasks are done so I could call the shutdown() method” but that is in contradiction to what you are actually doing in the code. You are calling awaitTermination after shutDown so you are not waiting in order to initiate the shutdown, but initiating the shutdown first and waiting for its completion then, which is the purpose of awaitTermination, waiting for the completion of the shutdown.
To put it in one sentence, just call shutDown after submission in order to shutdown the service after completion of all submitted jobs and don’t call awaitTermination unless you really want to wait for the termination.
Thanks to comment from VGR I solved my problem with creating yet another Thread in which I wrapped my existing code like this:
Thread thread = new Thread(() -> {
ExecutorService service = Executors.newCachedThreadPool();
collection.forEach(item -> service.submit(() -> {
// some computational work
});
try {
service.shutdown()
service.awaitTermination(2, TimeUnit.HOURS);
catch (InterruptedException iEx) {
// handle exception
}
});
thread.start();
return ResponseToClient();

How to preserve thread-safety of a CopyOnWriteArrayList with a correct run() method implementation?

I am using an ExecutorService with a fixedThreadPool. I create threads by implementing the Runnable interface. In the run() method, I am calling a time consuming function (let's say Thread.sleep() for now) and finally add an element to a thread safe CopyOnWriteArrayList. I am submitting threads in a for-loop. At the end of the for-loop I shutdown the ExecutorService and await termination.
However, the number of elements in the list does not turn out to be the same as the number of loop-iterations. Where is my mistake in concurrency thinking?
Here is a code example for this problem:
public class TestProgram {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(4);
CopyOnWriteArrayList<String> stringList = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 1000; i++) {
executor.submit(new myThread(stringList));
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
System.out.println(Integer.toString(stringList.size()));
}
}
class myThread implements Runnable {
CopyOnWriteArrayList<String> stringList;
public myThread(CopyOnWriteArrayList<String> stringList) {
this.stringList = stringList;
}
public void run() {
String string = new String("test");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(myThread.class.getName()).log(Level.SEVERE, null, ex);
}
stringList.add(string);
}
}
You're just not giving it enough time to complete. If you want to execute this serially you would need 1000 * 100 milliseconds, which is 100 seconds. You are running it with four threads, so divide that by 4 and you get 25 seconds. You only wait 10 seconds to complete. Increase that to 26 seconds just to be safe and you should see your result.
The ExecutorService#awaitTermination will wait the N number of seconds to complete, if it doesn't complete it will simply return out and continue the execution. To prove my point check the return value
System.out.println(executor.awaitTermination(10, TimeUnit.SECONDS));
The better solution here, is to use a new CountDownLatch(1000), have each Runnable task countDown after it adds to the list and finally have the main thread await completion.
The documentation of ExecutorService.shutdown says the following:
Initiates an orderly shutdown in which previously submitted tasks are
executed, but no new tasks will be accepted. Invocation has no
additional effect if already shut down.
This method does not wait for previously submitted tasks to complete
execution. Use awaitTermination to do that.
This means that you indicate your ExecutorService that it must stop it's services. Thus, this method sets a flag which indicates that the ExecutorService will end soon, which allows the main thread to returns from this method without problems.
ExecutorService.awaitTermination, moreover, reads as follows:
Blocks until all tasks have completed execution after a shutdown
request, or the timeout occurs, or the current thread is interrupted,
whichever happens first.
This means that the main thread will be blocked inside the method, where it will only be returned when the tasks sent to ExecutorService finish. In both cases, the developer intends to end the ExecutorService function. But with awaitTermination, the developer is saying ExecutorService should be terminated regardless of their tasks have been carried out or not.
As each task takes at least 100 milliseconds to complete, no one will possibly be completed because ExecutorService has a tolerance of only 10 milliseconds for completion of all it's tasks.
There is no point in calling shutdown and awaitTermination at the same time (or preceded by another). According to your code, shutdown has no effect. If you want your tasks to become completed, and that ExecutorService is terminated without caring if your main thread will continue, just use shutdown. If you do not want your main thread to be blocked, and simply want to end with ExecutorService, use shutdownNow.
If, on the other hand, you want your main thread to wait for the execution of your tasks without a certain time to be specified, you may have to use Java Synchronizers. Some of Java Synchronizers are as follow:
Latches
FutureTasks
Semaphores
Barriers
For your case, I believe you can use CountDownLatch. Make a new CountDownLatch object have the number of tasks running on your ExecutorService. As they are completed, the count is decreased, and so, your main thread can expect completion and continue after all.
I hope you have understood and you can do what you want. If you have further questions, the documentation of CountDownLatch demonstrates perfectly how you can synchronize tasks. Good luck.
In that code snippet one issue will be there.
executor.awaitTermination(10, TimeUnit.SECONDS);
Here it will wait for 10 seconds after that it will break.
You will try following snippet.
while (true) {
if(executor.awaitTermination(10, TimeUnit.SECONDS))
break;
}

Interrupt when waiting on a blocking queue

I have a Runnable that runs from an Executor.
The runnable is blocked waiting in an SychronousQueue.take. How can I make sure the take will be interrupted when I do executor.shutdown?
+1 to #Eugene. ExecutorService.shutdown() shuts the thread-pool down but any submitted jobs will continue to run until they finish. If you use shutdownNow() instead, it will actually interrupt the threads. This doesn't mean that they will stop immediately but it does mean that if they are blocked in queue.take() or their next call to queue.take() it will throw an InterruptedException so the thread can exit.
To quote from the Javadocs:
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
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.
When your threads are calling queue.take() they should have something like the following code:
try {
work = queue.take();
...
} catch (InterruptedException e) {
// re-interrupt the thread which is always a good pattern
Thread.currentThread().interrupt();
// quit the processing thread
return;
}
You can do something like this may be?
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIME)) {
executor.shutdownNow();
}
As specified in the javadoc of take it will throw an InterruptedException when the thread waiting is interrupted. So you need to make sure that your executor implementation will call Thread.interrupt() on all it's owning threads on shutdown.

Categories