If I use them both the same time (not sure if it's a good habit or not) in following example, what's the actual timeout?
ExecutorService executorService = executorServiceFactory.createThreads(2);
List<Callable<T>> tasksList = new ArrayList<>();
tasksList.add(task1);
tasksList.add(task2);
executorService.invokeAll(taskList);
// get the result object with 5 minutes timeout
final task1 = tasksList.get(0).get(5, TimeUnit.MINUTES);
final task2 = tasksList.get(1).get(5, TimeUnit.MINUTES);
executorService.shutdown();
// set the timeout to 30 seconds for executor service
executorService.awaitTermination(30, TimeUnit.SECONDS);
In the above example, I want to get the result of the completable future (used in other places), if I place a 5 minutes timeout in the get()
method, but I do shutdown the executor service and awaitTermination
for 30 seconds, which time will take effect? Is it 30 seconds? Since it's shorter than 5 minutes?
CodePudding user response:
You code may wait up to 10 minutes 30 seconds.
It will sequentially wait 3 times.
Code wait for 5 minute for first task, then another 5 minutes for second. So if second task isn't finished in 10 minutes it will wait another 30 second.
If first task finishes within less then 5 minutes it will wait for 5 minutes after first task is complete.
CodePudding user response:
tl;dr
- Read The Fine Manual, and search Stack Overflow.
- Capture
Future
objects returned by submitting tasks to executor service. - Use given boilerplate for executor service shut-down.
- Wait until after shut-down if you want results after all tasks complete.
Future#get
blocks until result is available, or until time-out expires, whichever comes first.
Details
Your code is not valid Java syntax.
- In
final task1 = …
, you must either declare a return type or use the wordvar
. - In
tasksList.get(0).get
. the firstget
returns aCallable
. ButCallable
does not have aget
method, so your second.get
fails.
List
of Future
objects
You should be capturing the List
of Future
objects returned by invokeAll
.
List < Future > futures = executorService.invokeAll( tasks ) ;
Your shut-down code is incomplete. The Javadoc gives you boilerplate, so use it. Modify this code to use time-outs appropriate to your situation. And I suggest replacing the var name pool
with ExecutorService
, as an executor service is not necessarily backed with a thread pool, nor should we really be thinking of an executor service as being merely a thread pool.
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 ex) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Since you want to gather results only after all the tasks complete, you should not be accessing the Future
objects until after this shutdownAndAwaitTermination
method returns. See the example code in Javadoc for Future
interface.
For example, if your tasks return a String
object:
for ( Future < String > future : futures )
{
try {
String result = future.get() ; // Use `Future` object to access its payload, the result of the task’s execution.
System.out.println( result ) ;
} catch ( ExecutionException e ) { … }
}
You said:
I do shutdown the executor service and awaitTermination for 30 seconds, which time will take effect? Is it 30 seconds? Since it's shorter than 5 minutes?
Reading the Javadoc would answer your questions. To quote:
ExecutorService#shutdown
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.ExecutorService#awaitTermination
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
Future#get
blocks
You asked:
if I place a 5 minutes timeout in the get() method
Apparently you meant Future#get
. The Javadoc says:
Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
“Waits” means this line blocks until either result is available or the time-out expires. So whatever code you have below this line is irrelevant.
If you have two calls to Future#get
, each with a 5-minute timeout, the first call waits up to five minutes, then the second call waits up to five minutes. So the maximum time total is about 10 minutes, while the minimum time is the time taken to immediately return each Future
object’s payload.
String result1 = myFuture1.get( 5 , TimeUnit.MINUTES ) ; // Blocks up to five minutes. Code below is irrelevant.
String result2 = myFuture2.get( 5 , TimeUnit.MINUTES ) ; // Blocks up to five minutes. Code below is irrelevant.
// At this point, up to 10 minutes may have elapsed maximum (appropriately).
I say "approximately" because timing is never exact in conventional Java (as opposed to real time Java). Java’s internal scheduling of tasks, and the host OS’ CPU scheduling of the JVM and its threads, means actual elapsed time may vary.
Project Loom
Project Loom is work being done on the OpenJDK project. Its aim is to bring new capabilities to Java’s threading and concurrency facilities.
Among the new features are virtual threads and structured concurrency. These are previewed and incubated (respectively) in Java 19.
These features may generally eliminate the need for CompletableFuture
which you mentioned but did not discuss. And these may provide a more convenient way to define a set of tasks to be completed together.
For more info, see:
- The JEPs linked above.
- The latest talks and interviews by members of the team such as Ron Pressler and Alan Bateman.
- The talks by the unnamed gentleman hosting the JEP Café channel on YouTube.
These topics have been addressed many times already on Stack Overflow. Always search thoroughly before posting. And search now to learn more.