I'n new to ExecutorService, but am unsure about my approach to this.
I could be dealing with up to 100 threads for a known task.
I'm using the general format below, where I create a List of FutureTasks, then submit these to the ExecutorService.
The ExecutorService returns and adds these pending results to another list.
I then iterate over this list, calling get() on each pending result.
My query is : won't this block on each get() in turn until all 100 threads have completed ? Is there a better way to do this ?
And am I right in assuming that get() returns the result of the Callable implementation's call() method ? I'm using the default FutureTask class, and haven't subclassed it.
ExecutorService exec = Executors.newFixedThreadPool( NUM_THREADS );
List<JobClass> originalList = new ArrayList<JobClass>();
List<SomeOtherClass> pendingResult = new ArrayList<SomeOtherClass>();
List<Future<SomeOtherClass>> resultList = new ArrayList<Future<SomeOtherClass>>();
for( JobClass sc : originalList )
pendingResult.add( submit( sc );
for( Future<SomeOtherClass> future : futures )
resultList.add( future.get(5, TimeUnit.SECONDS) );
Good question, if I understand you correctly, you are worried about consumption of the result of completed tasks. Yes the thread will block. Java's answer to that is using the CompletionService.
As mentioned in the documentation page "A service that decouples the production of new asynchronous tasks from the consumption of the results of completed tasks".
If you only proceed if all tasks are completed, you can do what you suggested. It will not matter in which order tasks complete. However, if you need to pass task results to other processor as soon as possible or do something else while tasks are executing, you may want to check if task is complete first using isDone method, for example, and call get() if it is complete.
Related
In C++ you can start a thread with a deferred or asynchronous launch policy. Is there a way to replicate this functionality in Java?
auto T1 = std::async(std::launch::deferred, doSomething());
auto T2 = std::async(std::launch::async, doSomething());
Descriptions of each--
Asynchronous:
If the async flag is set, then async executes the callable object f on a new thread of execution (with all thread-locals initialized) except that if the function f returns a value or throws an exception, it is stored in the shared state accessible through the std::future that async returns to the caller.
Deferred:
If the deferred flag is set, then async converts f and args... the same way as by std::thread constructor, but does not spawn a new thread of execution. Instead, lazy evaluation is performed: the first call to a non-timed wait function on the std::future that async returned to the caller will cause the copy of f to be invoked (as an rvalue) with the copies of args... (also passed as rvalues) in the current thread (which does not have to be the thread that originally called std::async). The result or exception is placed in the shared state associated with the future and only then it is made ready. All further accesses to the same std::future will return the result immediately.
See the documentation for details.
Future
First of all, we have to observe that std::async is a tool to execute a given task and return a std::future object that holds the result of the computation once its available.
For example we can call result.get() to block and wait for the result to arrive. Also, when the computation encountered an exception, it will be stored and rethrown to us as soon as we call result.get().
Java provides similar classes, the interface is Future and the most relevant implementation is CompletableFuture.
std::future#get translates roughly to Future#get. Even the exceptional behavior is very similar. While C++ rethrows the exception upon calling get, Java will throw a ExecutionException which has the original exception set as cause.
How to obtain a Future?
In C++ you create your future object using std::async. In Java you could use one of the many static helper methods in CompletableFuture. In your case, the most relevant are
CompletableFuture#runAsync, if the task does not return any result and
CompletableFuture#supplyAsync, if the task will return a result upon completion
So in order to create a future that just prints Hello World!, you could for example do
CompletableFuture<Void> task = CompletableFuture.runAsync(() -> System.out.println("Hello World!"));
/*...*/
task.get();
Java not only has lambdas but also method references. Lets say you have a method that computes a heavy math task:
class MyMath {
static int compute() {
// Very heavy, duh
return (int) Math.pow(2, 5);
}
}
Then you could create a future that returns the result once its available as
CompletableFuture<Integer> task = CompletableFuture.runAsync(MyMath::compute);
/*...*/
Integer result = task.get();
async vs deferred
In C++, you have the option to specify a launch policy which dictates the threading behavior for the task. Let us put the memory promises C++ makes aside, because in Java you do not have that much control over memory.
The differences are that async will immediately schedule creation of a thread and execute the task in that thread. The result will be available at some point and is computed while you can continue work in your main task. The exact details whether it is a new thread or a cached thread depend on the compiler and are not specified.
deferred behaves completely different to that. Basically nothing happens when you call std::async, no extra thread will be created and the task will not be computed yet. The result will not be made available in the meantime at all. However, as soon as you call get, the task will be computed in your current thread and return a result. Basically as if you would have called the method directly yourself, without any async utilities at all.
std::launch::async in Java
That said, lets focus on how to translate this behavior to Java. Lets start with async.
This is the simple one, as it is basically the default and intended behavior offered in CompletableFuture. So you just do runAsync or supplyAsync, depending on whether your method returns a result or not. Let me show the previous examples again:
// without result
CompletableFuture<Void> task = CompletableFuture.runAsync(() -> System.out.println("Hello World!"));
/*...*/ // the task is computed in the meantime in a different thread
task.get();
// with result
CompletableFuture<Integer> task = CompletableFuture.supplyAsync(MyMath::compute);
/*...*/
Integer result = task.get();
Note that there are also overloads of the methods that except an Executor which can be used if you have your own thread pool and want CompletableFuture to use that instead of its own (see here for more details).
std::launch::deferred in Java
I tried around a lot to mock this behavior with CompletableFuture but it does not seem to be possibly without creating your own implementation (please correct me if I am wrong though). No matter what, it either executes directly upon creation or not at all.
So I would just propose to use the underlying task interface that you gave to CompletableFuture, for example Runnable or Supplier, directly. In our case, we might also use IntSupplier to avoid the autoboxing.
Here are the two code examples again, but this time with deferred behavior:
// without result
Runnable task = () -> System.out.println("Hello World!");
/*...*/ // the task is not computed in the meantime, no threads involved
task.run(); // the task is computed now
// with result
IntSupplier task = MyMath::compute;
/*...*/
int result = task.getAsInt();
Modern multithreading in Java
As a final note I would like to give you a better idea how multithreading is typically used in Java nowadays. The provided facilities are much richer than what C++ offers by default.
Ideally should design your system in a way that you do not have to care about such little threading details. You create an automatically managed dynamic thread pool using Executors and then launch your initial task against that (or use the default executor service provided by CompletableFuture). After that, you just setup an operation pipeline on the future object, similar to the Stream API and then just wait on the final future object.
For example, let us suppose you have a list of file names List<String> fileNames and you want to
read the file
validate its content, skip it if its invalid
compress the file
upload the file to some web server
check the response status code
and count how many where invalid, not successfull and successfull. Suppose you have some methods like
class FileUploader {
static byte[] readFile(String name) { /*...*/ }
static byte[] requireValid(byte[] content) throws IllegalStateException { /*...*/ }
static byte[] compressContent(byte[] content) { /*...*/ }
static int uploadContent(byte[] content) { /*...*/ }
}
then we can do so easily by
AtomicInteger successfull = new AtomicInteger();
AtomicInteger notSuccessfull = new AtomicInteger();
AtomicInteger invalid = new AtomicInteger();
// Setup the pipeline
List<CompletableFuture<Void>> tasks = fileNames.stream()
.map(name -> CompletableFuture
.completedFuture(name)
.thenApplyAsync(FileUploader::readFile)
.thenApplyAsync(FileUploader::requireValid)
.thenApplyAsync(FileUploader::compressContent)
.thenApplyAsync(FileUploader::uploadContent)
.handleAsync((statusCode, exception) -> {
AtomicInteger counter;
if (exception == null) {
counter = statusCode == 200 ? successfull : notSuccessfull;
} else {
counter = invalid;
}
counter.incrementAndGet();
})
).collect(Collectors.toList());
// Wait until all tasks are done
tasks.forEach(CompletableFuture::join);
// Print the results
System.out.printf("Successfull %d, not successfull %d, invalid %d%n", successfull.get(), notSuccessfull.get(), invalid.get());
The huge benefit of this is that it will reach max throughput and use all hardware capacity offered by your system. All tasks are executed completely dynamic and independent, managed by an automatic pool of threads. And you just wait until everything is done.
For asynchronous launch of a thread, in modern Java prefer the use of a high-level java.util.concurrent.ExecutorService.
One way to obtain an ExecutorService is through java.util.concurrent.Executors. Different behaviors are available for ExecutorServices; the Executors class provides methods for some common cases.
Once you have an ExecutorService, you can submit Runnables and Callables to it.
Future<MyReturnValue> myFuture = myExecutorService.submit(myTask);
If I understood you correctly, may be something like this:
private static CompletableFuture<Void> deferred(Runnable run) {
CompletableFuture<Void> future = new CompletableFuture<>();
future.thenRun(run);
return future;
}
private static CompletableFuture<Void> async(Runnable run) {
return CompletableFuture.runAsync(run);
}
And then using them like:
public static void main(String[] args) throws Exception {
CompletableFuture<Void> def = deferred(() -> System.out.println("run"));
def.complete(null);
System.out.println(def.join());
CompletableFuture<Void> async = async(() -> System.out.println("run async"));
async.join();
}
To get something like a deferred thread, you might try running a thread at a reduced priority.
First, in Java it's often idiomatic to make a task using a Runnable first. You can also use the Callable<T> interface, which allows the thread to return a value (Runnable can't).
public class MyTask implements Runnable {
#Override
public void run() {
System.out.println( "hello thread." );
}
}
Then just create a thread. In Java threads normally wrap the task they execute.
MyTask myTask = new MyTask();
Thread t = new Tread( myTask );
t.setPriority( Thread.currentThread().getPriority()-1 );
t.start();
This should not run until there is a core available to do so, which means it shouldn't run until the current thread is blocked or run out of things to do. However you're at the mercy of the OS scheduler here, so the specific operation is not guaranteed. Most OSs will guarantee that all threads run eventually, so if the current thread takes a long time with out blocking the OSs will start it executing anyway.
setPriority() can throw a security exception if you're not allowed to set the priority of a thread (uncommon but possible). So just be aware of that minor inconvenience.
For an asynch task with a Future I would use an executor service. The helper methods in the class Executors are a convenient way to do this.
First make your task as before.
public class MyCallable implements Callable<String> {
#Override
public String call() {
return "hello future thread.";
}
}
Then use an executor service to run it:
MyCallable myCallable = new MyCallable();
ExecutorService es = Executors.newCachedThreadPool();
Future<String> f = es.submit( myCallable );
You can use the Future object to query the thread, determine its running status and get the value it returns. You will need to shutdown the executor to stop all of its threads before exiting the JVM.
es.shutdown();
I've tried to write this code as simply as possible, without the use of lambdas or clever use of generics. The above should show you what those lambdas are actually implementing. However it's usually considered better to be a bit more sophisticated when writing code (and a bit less verbose) so you should investigate other syntax once you feel you understand the above.
I have to start unknown number of threads then wait or all threads to finish their job. I am using executor service. I tried using countdownlatch - so that I may wait till countdown is zero.
But there is no way I can get number of threads I have started. Can someone give me any idea how may I achieve this ?
Thank you for your responses. I came across the answer, and it helped. Sharing a link for reference.
Flexible CountDownLatch?
In case that you want combine a List of CompletableFutures, you can do this :
// Waits for *all* futures to complete and returns a list of results.
// If *any* future completes exceptionally then the resulting future will also complete exceptionally.
public static <T> CompletableFuture<List<T>> all(List<CompletableFuture<T>> futures) {
CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);
return CompletableFuture.allOf(cfs)
.thenApply(ignored -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
For more details on Future & CompletableFuture, useful links:
Future: https://www.baeldung.com/java-future
CompletableFuture: https://www.baeldung.com/java-completablefuture
CompletableFuture: https://www.callicoder.com/java-8-completablefuture-tutorial/
Waiting on a list of Future
I...really don't know how to word the title better. But basically, what I have is a thread pool with all these threads busily working. I want them to report their results in the order that they were assigned, but at the same time, I want to work in batches. To illustrate, and example would be
ExecutorService exec = Executors.newFixedThreadPool(8);
class MyCallable implements Callable<byte[]> {
private final int threadnumber;
MyCallable(int threadnumber){
this.threadnumber = threadnumber;
}
public byte[] call() {
//does something
}
}
List<Callable<byte[]>> callables = new ArrayList<Callable<byte[]>>();
for(int i=1; i<=20; i++) {
callables.add(new MyCallable(i));
}
try {
List<Future<byte[]>> results = exec.invokeAll(callables);
for(Future<byte[]> result: results) {
System.out.write(result.get(), 0, result.get().length);
}
Basically, the pool thread has 8 threads and I end up having 20 tasks (these are just examples). The way this works now, if I understand correctly, is that it waits until ALL 20 tasks are done before outputting them in order (from 1 to 20). What this program is supposed to do is output a continuous stream of bytes (which were processed by threads, and since I need to keep the order intact, I used the future interface). While I don't mind waiting until all 20 tasks are done, is there anyway so that the threads simply output in order as they go.
If there's no way or I'm just completely misunderstanding how invokeAll works, clarification there is welcome too. Thanks a bunch in advance! Executors are a bit confusing since I only just learned about them.
Random addendum, am I even allowed to return a byte array from a callable?
invokeAll() waits until all results are computed before it returns.
Use a loop and submit() them one by one instead, this method returns a Future with the pending result immediately:
...
for(int i=1; i<=20; i++) {
results.add(exec.submit(new MyCallable(i)));
}
try {
for(Future<Integer> result: results) {
System.out.write(result.get(), 0, result.get().length);
}
}
...
Using invokeAll also you can achieve.
List<Future<byte[]>> results = exec.invokeAll(callables);
It will return the future object list.
ThreadPoll will execute the tasks in random order . Task execution order cannnot be controlled.
Future Object
Its a reference of task which is submitted in ThreadPool.
It has a method get(). Its a blocking call method. If you invoke the get() method ,call will be wait until tasks get completed.
How to ensure Tasks submission order
Results order is same in callables order. Even thread pool will execute in different order we can retrieve in same order.
For Ex .
Three Tasks 1,2,3
1 & 3 --> Completed.
2 ------> Taking long time to execute.
After calling invokeAll method It will return List of Future in same order.
Task 1 : Future#get method return result since its already completed
Task 2 : Future#get method waits till task will complete.
Iteration waits till second task will complete even though third task completed. It wont get result from third thread.
Given this code,
Collection<?> callables = ...
ExecutorService executorService = ...
List<Future<?>> futures = executorService.invokeAll(callables, TIMEOUT, TimeUnit.SECONDS);
I'd like to know which of the callables were cancelled (did not finish in time). I know I can query each Future with .isCancelled() but that gives me no information as to which exact Callable was cancelled.
One solution would be for Future to implement a toString() method that delegates to the underlying toString() of Callable. Unfortunately, this is not done.
I know I can query each Future with .isCancelled() but that gives me no information as to which exact Callable was cancelled.
The list of Futures is in the same order as the list of Callables it was created from. So you can keep track that way.
This question already has answers here:
How to wait for all threads to finish, using ExecutorService?
(27 answers)
Closed 5 years ago.
I need to submit a number of task and then wait for them until all results are available. Each of them adds a String to a Vector(that is synchronized by default). Then I need to start a new task for each result in the Vector but I need to do this only when all the previous tasks have stopped doing their job.
I want to use Java Executor, in particular I tried using Executors.newFixedThreadPool(100) in order to use a fixed number of thread (I have a variable number of task that can be 10 or 500) but I'm new with executors and I don't know how to wait for task termination.
This is something like a pseudocode of what my program needs to do:
ExecutorService e = Executors.newFixedThreadPool(100);
while(true){
/*do something*/
for(...){
<start task>
}
<wait for all task termination>
for each String in result{
<start task>
}
<wait for all task termination>
}
I can't do a e.shutdown because I'm in a while(true) and I need to reuse the executorService...
Can you help me? Can you suggest me a guide/book about java executors?
The ExecutorService gives you a mechanism to execute multiple tasks simultaneously and get a collection of Future objects back (representing the asynchronous computation of the task).
Collection<Callable<?>> tasks = new LinkedList<Callable<?>>();
//populate tasks
for (Future<?> f : executorService.invokeAll(tasks)) { //invokeAll() blocks until ALL tasks submitted to executor complete
f.get();
}
If you have Runnables instead of Callables, you can easily turn a Runnable into a Callable<Object> using the method:
Callable<?> c = Executors.callable(runnable);
Can you suggest me a guide/book about
java executors??
I can answer this part:
Java Concurrency in Practice by Brian Goetz (with Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea) is most likely your best bet.
It's not only about executors though, but instead covers java.util.concurrent package in general, as well as basic concurrency concepts and techniques, and some advanced topics such as the Java memory model.
Rather than submitting Runnables or Callables to an Executor directly and storing the corresponding Future return values I'd recommend using a CompletionService implementation to retrieve each Future when it completes. This approach decouples the production of tasks from the consumption of completed tasks, allowing for example new tasks to originate on a producer thread over a period of time.
Collection<Callable<Result>> workItems = ...
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletionService<Result> compService = new ExecutorCompletionService<Result>(executor);
// Add work items to Executor.
for (Callable<Result> workItem : workItems) {
compService.submit(workItem);
}
// Consume results as they complete (this would typically occur on a different thread).
for (int i=0; i<workItems.size(); ++i) {
Future<Result> fut = compService.take(); // Will block until a result is available.
Result result = fut.get(); // Extract result; this will not block.
}
When you submit to an executor service, you'll get a Future object back.
Store those objects in a collection, and then call get() on each in turn. get() blocks until the underlying job completes, and so the result is that calling get() on each will complete once all underlying jobs have finished.
e.g.
Collection<Future> futures = ...
for (Future f : futures) {
Object result = f.get();
// maybe do something with the result. This could be a
// genericised Future<T>
}
System.out.println("Tasks completed");
Once all these have completed, then begin your second submission. Note that this might not be an optimal use of your thread pool, since it will become dormant, and then you're re-populating it. If possible try and keep it busy doing stuff.
ExecutorService executor = ...
//submit tasks
executor.shutdown(); // previously submitted tasks are executed,
// but no new tasks will be accepted
while(!executor.awaitTermination(1, TimeUnit.SECONDS))
;
There's no easy way to do what you want without creating custom ExecutorService.