Behaviour of ForkJoinPool in CompletableFuture.supplyAsync() - java

I'm comparing the behaviour of CompletableFuture.supplyAsync() in the two cases in which I set a custom ExecutorService or I want my Supplier to be executed by the default executor (if not specified) which is ForkJoinPool.commonPool()
Let's see the difference:
public class MainApplication {
public static void main(final String[] args) throws ExecutionException, InterruptedException {
Supplier<String> action1 = () -> {
try {
Thread.sleep(3000);
}finally {
return "Done";
}
};
Function<String, String> action2 = (input) -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
return input + "!!";
}
};
final ExecutorService executorService = Executors.newFixedThreadPool(4);
CompletableFuture.supplyAsync(action1, executorService)
.thenApply (action2)
.thenAccept (res -> System.out.println(res));
System.out.println("This is the end of the execution");
}
}
In this case I'm passing executorService to my supplyAsync() and it prints:
This is the end of the execution
Done!!
So "Done" gets printed after the end of the main execution.
BUT if I use instead:
CompletableFuture.supplyAsync(action1)
so I don't pass my custom executorService and the CompletableFuture class uses under the hood the ForkJoinPool.commonPool() then "Done" is not printed at all:
This is the end of the execution
Process finished with exit code 0
Why?

In both cases when you do
CompletableFuture.supplyAsync(action1, executorService)
.thenApply (action2)
.thenAccept (res -> System.out.println(res));
you don't wait for task completition. But then you program is going to exit and there is differences how common fork join pool:
ForkJoinPool.commonPool()
and regular executor service:
final ExecutorService executorService = Executors.newFixedThreadPool(4);
..react on attempt to call System.exit(...) equivalent.
This is what doc says about fork join common pool, you should point attention to that:
However this pool and any ongoing processing are automatically
terminated upon program System.exit(int). Any program that relies on
asynchronous task processing to complete before program termination
should invoke commonPool().awaitQuiescence, before exit.
That is link to ExecutorService docs, you may point attention to:
The shutdown() method will allow previously submitted tasks to execute
before terminating
I think that may be a difference you asking about.

ForkJoinPool uses daemon threads that does not prevent JVM from exiting. On the other hand the threads in the ExecutorService created by Executors are non-daemon threads, hence it keeps JVM from exiting until you explicitly shutdown the thread pool.
Also notice that in your example you need to shutdown the pool at the end in order to terminate the JVM.
executorService.shutdown();
So, one solution would be to keep the main thread waiting for few seconds until your computation is completed like so,
Thread.sleep(4000);

Related

Java CompletableFuture using allOf : if one thread throws exception, how to immediately stop execution of all threads?

// assume: serviceCall1 throws an exception after 1s, servserviceCall2 runs 10s without exception
CompletableFuture<String> serviceCall1Future = serviceCall1.execute();
CompletableFuture<String> serviceCall2Future = serviceCall2.execute();
CompletableFuture<Void> allOffFuture = CompletableFuture.allOf(serviceCall1Future, serviceCall2Future);
// does not work, will be called after thread 2 has finished
allOffFuture.exceptionally( ex -> { allOffFuture.cancel(true); return null; } );
try {
// waiting for threads to finish
allOffFuture.join();
} catch (CompletionException e) {
// does not work, here we come after thread 2 has finished
allOffFuture.cancel(true);
}
If one thread throws an exception, in my case it doesnt make any sense for the other thread(s) to keep on running, so I want them both (all in case of more than 2 threads) to stop . How can I achieve that ?
I guess something like this should work:
CompletableFuture<String> serviceCall1Future = serviceCall1.execute();
CompletableFuture<String> serviceCall2Future = serviceCall2.execute();
CompletableFuture<String> foo1 = serviceCall1Future.whenComplete((result,exception) -> {if(exception != null) serviceCall2Future.cancel(true);});
CompletableFuture<String> foo2 = serviceCall2Future.whenComplete((result,exception) -> {if(exception != null) serviceCall1Future.cancel(true);});
CompletableFuture<Void> allOffFuture = CompletableFuture.allOf(foo1, foo2);
// ... rest of your code
This cancels the other future when the one completes with an exception.
If you are using an ExecutorService with CompletableFuture, you can use Shutdowns methods like shutdown() or shutdownNow().
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt. Here is an example of calling ExecutorService shutdownNow()
See -> https://jenkov.com/tutorials/java-util-concurrent/executorservice.html#executorservice-shutdown

Own ExecutorService used to create CompletableFuture does not terminate

I'm trying to use my own ExecutorService to create a set of CompletableFutures to chain several process steps. These steps might throw exceptions.
When they do, it seems to me the thread in the ExecutorService is not released although I'm trying to handle this case.
class Scratch {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
AtomicInteger counter = new AtomicInteger();
Supplier<?> throwingException = () -> { throw new RuntimeException("throw " + counter.incrementAndGet()); };
Function<String, CompletableFuture<?>> process =
url -> CompletableFuture.supplyAsync(throwingException, executor)
.exceptionally(Scratch::log);
var collect = IntStream.range(1, 10).mapToObj(i -> "url" + i)
.map(process)
.toArray(CompletableFuture[]::new);
final CompletableFuture<Void> together = CompletableFuture.allOf(collect);
System.out.println("joining");
together.exceptionally(Scratch::log).join();
System.out.println("finished");
if (executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("exiting cleanly");
} else {
System.out.println("not terminated");
}
executor.submit(() -> System.out.println("still executing"));
}
static <T> T log(Throwable t) {
System.out.println(t.getMessage());
return null;
}
}
Output is
java.lang.RuntimeException: throw 1
joining
java.lang.RuntimeException: throw 2
java.lang.RuntimeException: throw 3
java.lang.RuntimeException: throw 4
java.lang.RuntimeException: throw 5
java.lang.RuntimeException: throw 6
java.lang.RuntimeException: throw 7
java.lang.RuntimeException: throw 8
java.lang.RuntimeException: throw 9
finished
not terminated
The process started by this also isn't terminated (which is how I noticed).
It seems to me this should mean there are no threads left in the ExecutorService at this point, but that doesn't seem to be the case; if we lower the thread pool capacity, it will still run all submitted tasks, and if we add submit another after the failed termination (eg executor.submit(() -> System.out.println("still executing"));), it will get executed.
If we don't pass our own ExecutorService to the CompletableFutre::supplyAsync, the process will terminate as expected.
I also tried other versions of handling the exceptional state (like using together.whenComplete()), but that has the same result.
Why is this happening, and how can I make sure the ExecutorService terminates correctly?
EDIT: I realized that it's not the exception that's causing the problem, this will occur with any task provided to CompletableFuture with your own executor service, which makes total sense given Eugene's reply. I'm changing the question title.
There are two things going on here. First one is that when you execute without an explicit Executor, your actions run in the ForkJoinPool. That pool uses daemon-threads, which do not stop the VM to exit. So when your main is over, VM exists.
The second point is in the documentation of awaitTermination, actually:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
Since you did not call shutDown and that pool creates non-daemon threads, the process does not exit.

ExecutorService for Do-While Loop in Java

I am new to concurrency and I was trying to implement executor service concurrency for a do-while loop. But I always run into RejectedExecutionException
Here is my sample code:
do {
Future<Void> future = executor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
// action
return null;
}
});
futures.add(future);
executor.shutdown();
for (Future<Void> future : futures) {
try {
future.get();
}
catch (InterruptedException e) {
throw new IOException(e)
}
}
}
while (true);
But this seems incorrect. I think I am calling the shutdown at the wrong place. Can anyone please help me implement Executor Service in a do-while loop correctly. Thanks.
ExecutorService.shutdown() stops the ExecutorService from accepting anymore jobs. It should be called when you're done submitting jobs.
Also Future.get() is a blocking method, which means it will block the execution of current thread and next iteration of loop will not continue unless this future (on which the get is called) returns. This will happen in every iteration, which makes the code non parallel.
You can use a CountDownLatch to wait for all the jobs to return.
Following is the correct code.
final List<Object> results = Collections.synchronizedList(new ArrayList<Object>());
final CountDownLatch latch = new CountDownLatch(10);//suppose you'll have 10 futures
do {
Future<Void> future = executor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
// action
latch.countDown();//decrease the latch count
results.add(result); // some result
return null;
}
});
futures.add(future);
} while (true);
executor.shutdown();
latch.await(); //This will block till latch.countDown() has been called 10 times.
//Now results has all the outputs, do what you want with them.
Also if you're working with Java 8 then you can take a look at this answer https://stackoverflow.com/a/36261808/5343269
You're right, the shutdown method is not being called at the correct time. The ExecutorService will not accept tasks after shutdown is called (unless you implement your own version that does).
You should call shutdown after you've already submitted all tasks to the executor, so in this case, somewhere after the do-while loop.
From ThreadPoolExecutor documentation:
Rejected tasks
New tasks submitted in method execute(Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.
In either case, the execute method invokes the RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) method of its RejectedExecutionHandler
From your code, it's clearly evident that you are calling shutdown() first and submitting the tasks later.
On a different note, refer to this related SE question for right way of shutting down ExecutorService:
ExecutorService's shutdown() doesn't wait until all threads will be finished

How can we save a thread for next task after its execution in java (Implementation of Thread pooling )

I need to ask about how thread pooling is implemented for having constant number of thread executing each time when there is task submission happened . (In Executor to avoid each time thread creation and deletion overhead)
executor.submit(Runnable)
Lets say we create some threads in the start and when task come we assign task to them(Thread) using any Queue impl . But after completing it s task how could a thread return to its pool again when as per the lifecycle of thread says that
"After execution of its run method it goes into TERMINATED state and can't be used again"
I am not understood how thread pool works for having constant number of threads for execution of any task to its queue .
It would be great if anyone could provide me an example of thread reuse after its completion of task .
!!Thanks in advance .!!
"After execution of its run method it goes into TERMINATED state and can't be used again"
It doesn't finish its run() Instead it has a loop which runs the run() of the tasks you provide it.
Simplifying the thread pool pattern dramatically you have code which looks like this.
final BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>();
public void submit(Runnable runs) {
tasks.add(runs);
}
volatile boolean running = true;
// running in each thread in the pool
class RunsRunnable implement Runnable {
public void run() {
while(running) {
Runnable runs = tasks.take();
try {
runs.run();
} catch(Throwable t) {
// handles t
}
}
}
}
In this example, you can see that while the run() of each task completes, the run() of the thread itself does not until the pool is shutdown.
Usually what happens when we use thread pool , Its inside Run method it is forced to run iteratively. Until there are tasks available in the Queue.
in the below example pool.removeFromQueue() will run iteratively.
public class MyThread<V> extends Thread {
private MyThreadPool<V> pool;
private boolean active = true;
public boolean isActive() {
return active;
}
public void setPool(MyThreadPool<V> p) {
pool = p;
}
/**
* Checks if there are any unfinished tasks left. if there are , then runs
* the task and call back with output on resultListner Waits if there are no
* tasks available to run If shutDown is called on MyThreadPool, all waiting
* threads will exit and all running threads will exit after finishing the
* task
*/
#Override
public void run() {
ResultListener<V> result = pool.getResultListener();
Callable<V> task;
while (true) {
task = pool.removeFromQueue();
if (task != null) {
try {
V output = task.call();
result.finish(output);
} catch (Exception e) {
result.error(e);
}
} else {
if (!isActive())
break;
else {
synchronized (pool.getWaitLock()) {
try {
pool.getWaitLock().wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
void shutdown() {
active = false;
}
Need to design your thread pool
public MyThreadPool(int size, ResultListener<V> myResultListener) {
tasks = new LinkedList<Callable<V>>();
threads = new LinkedList<MyThread<V>>();
shutDown = false;
resultListener = myResultListener;
for (int i = 0; i < size; i++) {
MyThread<V> myThread = new MyThread<V>();
myThread.setPool(this);
threads.add(myThread);
myThread.start();
}
}
You can take a look here: http://www.ibm.com/developerworks/library/j-jtp0730/index.html for more details and an implementation example. The threads in the pool will wait if the queue is empty and will each start consome messages once they are notified that the queue has some elements.
ExecutorService executor = Executors.newFixedThreadPool(2);
- The above statement created a ThreadPool with fixed size of 2.
executor.execute(new Worker());
- The above statement takes an instance of the class Worker which has implemented Runnable Interface.
- Now here the Executors is an intermediate object, executing the task. Which manages the Thread Objects.
- By executing the above statement the run() method will be executed, and once the run() method completes, the thread doesNot go into dead state but moves back into the pool, waiting to have another work assigned to it, so it can once again move into Runnable state and then to running, all this is handled by Executors .
executor.shutdown();
- The above statement will shutdown the Executors itself, gracefully handling the shutdown of all the threads managed by it..shutdown() on that central object, which in turn could terminate each of the registered executors.
////////// Edited Part//////////////////////
- First of all Runnable has a run() method which canNot return anything, and run() method canNot throw a checked exception, So Callable was introduced in Java 5, which is of Parametric type , and has a method called call(), and it is capable of returning , and throwing Checked exceptions.
Now see this Example:
Thread t = new Thread(new Worker());
t.run();
t.start();
- t.run() is just a simple call to run() method, this won't span a thread of execution.
- t.start() whereas prepares for the things important for the initialization of the thread of execution, and then calls the run() method of the Runnable, and then assign the Task to the newly formed thread of execution, and returns quickly....
Threads in Java becomes a necessity when using Swing and AWT. Mainly the GUI component.
I am totally agree with Peter but want add steps related to ExecutorService execution flow, for clear understanding.
If you create pool (fixed size pool) of threads it does not means that threads were created.
If you submit and/or execute new Task (Runnuble or Callable) new thread will be created JUTS if count of created threads < size of pool
Created threads not returning to pool, threads can wait for new value in blocking queue, this point we can call RETURNING TO POOL
All threads from pool execs like Peter described above.

How to implement an ExecutorService to execute batches of tasks

I am looking for a way to execute batches of tasks in java. The idea is to have an ExecutorService based on a thread pool that will allow me to spread a set of Callable among different threads from a main thread. This class should provide a waitForCompletion method that will put the main thread to sleep until all tasks are executed. Then the main thread should be awaken, and it will perform some operations and resubmit a set of tasks.
This process will be repeated numerous times, so I would like to use ExecutorService.shutdown as this would require to create multiple instances of ExecutorService.
Currently I have implemented it in the following way using a AtomicInteger, and a Lock/Condition:
public class BatchThreadPoolExecutor extends ThreadPoolExecutor {
private final AtomicInteger mActiveCount;
private final Lock mLock;
private final Condition mCondition;
public <C extends Callable<V>, V> Map<C, Future<V>> submitBatch(Collection<C> batch){
...
for(C task : batch){
submit(task);
mActiveCount.incrementAndGet();
}
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
mLock.lock();
if (mActiveCount.decrementAndGet() == 0) {
mCondition.signalAll();
}
mLock.unlock();
}
public void awaitBatchCompletion() throws InterruptedException {
...
// Lock and wait until there is no active task
mLock.lock();
while (mActiveCount.get() > 0) {
try {
mCondition.await();
} catch (InterruptedException e) {
mLock.unlock();
throw e;
}
}
mLock.unlock();
}
}
Please not that I will not necessarily submit all the tasks from the batch at once, therefore CountDownLatch does not seem to be an option.
Is this a valid way to do it? Is there a more efficient/elegant way to implement that?
Thanks
I think the ExecutorService itself will be able to perform your requirements.
Call invokeAll([...]) and iterate over all of your Tasks. All Tasks are finished, if you can iterate through all Futures.
As the other answers point out, there doesn't seem to be any part of your use case that requires a custom ExecutorService.
It seems to me that all you need to do is submit a batch, wait for them all to finish while ignoring interrupts on the main thread, then submit another batch perhaps based on the results of the first batch. I believe this is just a matter of:
ExecutorService service = ...;
Collection<Future> futures = new HashSet<Future>();
for (Callable callable : tasks) {
Future future = service.submit(callable);
futures.add(future);
}
for(Future future : futures) {
try {
future.get();
} catch (InterruptedException e) {
// Figure out if the interruption means we should stop.
}
}
// Use the results of futures to figure out a new batch of tasks.
// Repeat the process with the same ExecutorService.
I agree with #ckuetbach that the default Java Executors should provide you with all of the functionality you need to execute a "batch" of jobs.
If I were you I would just submit a bunch of jobs, wait for them to finish with the ExecutorService.awaitTermination() and then just start up a new ExecutorService. Doing this to save on "thread creations" is premature optimization unless you are doing this 100s of times a second or something.
If you really are stuck on using the same ExecutorService for each of the batches then you can allocate a ThreadPoolExecutor yourself, and be in a loop looking at ThreadPoolExecutor.getActiveCount(). Something like:
BlockingQueue jobQueue = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(NUM_THREADS, NUM_THREADS,
0L, TimeUnit.MILLISECONDS, jobQueue);
// submit your batch of jobs ...
// need to wait a bit for the jobs to start
Thread.sleep(100);
while (executor.getActiveCount() > 0 && jobQueue.size() > 0) {
// to slow the spin
Thread.sleep(1000);
}
// continue on to submit the next batch

Categories

Resources