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
Related
I am running several hundred functions with runAsync(). All of the functions modify some statically available list and thus do not need to return anything. I want to make sure they all finish before continuing my processing. Is this the appropriate way to wait? Is there a simpler way to accomplish what I'm trying to do?
List<CompletableFuture<Void>> futures = new ArrayList<>();
active_sites.forEach(site -> site.getEntryPoints().stream().map(EntryPoint::scanEntryPoint).forEach(futures::add));
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
You can simplify that quite a bit:
CompletableFuture[] scans = active_sites.stream()
.flatMap(site -> site.getEntryPoints().stream())
.map(EntryPoint::scanEntryPoint)
.toArray(CompletableFuture[]::new)
CompletableFuture.allOf(scans).join();
I am on plain JDK 8. I have this simple RxJava example:
Observable
.from(Arrays.asList("one", "two", "three"))
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word, Thread.currentThread().getName()))
//.subscribeOn(Schedulers.newThread())
.subscribe(word -> System.out.println(word));
and it prints out the words line by line, intertwined with information about the thread, which is 'main' for all next calls, as expected.
However, when I uncomment the subscribeOn(Schedulers.newThread()) call, nothing is printed at all. Why isn't it working? I would have expected it to start a new thread for each onNext() call and the doOnNext() to print that thread's name. Right now, I see nothing, also for the other schedulers.
When I add the call to Thread.sleep(10000L) at the end of my main, I can see the output, which would suggest the threads used by RxJava are all daemons. Is this the case? Can this be changed somehow, but using a custom ThreadFactory or similar concept, and not have to implement a custom Scheduler?
With the mentioned change, the thread name is always RxNewThreadScheduler-1, whereas the documentation for newThread says "Scheduler that creates a new {#link Thread} for each unit of work". Isn't it supposed to create a new thread for all of the emissions?
As Vladimir mentioned, RxJava standard schedulers run work on daemon threads which terminate in your example because the main thread quits. I'd like to emphasise that they don't schedule each value on a new thread, but they schedule the stream of values for each individual subscriber on a newly created thread. Subscribing a second time would give you "RxNewThreadScheduler-2".
You don't really need to change the default schedulers, but just wrap your own Executor-based scheduler with Schedulers.from() and supply that as a parameter where needed:
ThreadPoolExecutor exec = new ThreadPoolExecutor(
0, 64, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
exec.allowCoreThreadTimeOut(true);
Scheduler s = Schedulers.from(exec);
Observable
.from(Arrays.asList("one", "two", "three"))
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribeOn(s)
.subscribe(word -> System.out.println(word));
I've got a series of blog posts about RxJava schedulers whichs should help you implement a "more permanent" variant.
Contrary to newcomers belief, reactive streams are not inherently concurrent but are inherently asynchronous. They also are inherently sequential and concurrency must be configured within the stream. Put simply, reactive streams are naturally sequential at their ends but can be concurrent at their core.
The secret sauce is using the flatMap() operator within the stream. This operator takes an Observable<T> input from the source stream and, internally re-emit it as an Observable<Observable<T>> stream to which it subscribes too all instances at once. As long as the flatMap() internal stream is executed in a multi-threaded context, it will concurrently execute the provided Function<T, R> that applies your logic and, finally, re-emit the result on the original stream as it's own emissions.
This sounds very complicated (and it is quite a bit at first glance) but simple examples with explanations help to understand the concept.
Find more details from a similar question here and articles on RxJava2 Schedulers and Concurrency with code sample and detailed explanations on how to use Schedulers sequentially and concurrently.
Hope this helps,
Softjake
public class MainClass {
public static void main(String[] args) {
Scheduler scheduler = Schedulers.from(Executors.newFixedThreadPool(10, Executors.defaultThreadFactory()));
Observable.interval(1,TimeUnit.SECONDS)
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribeOn(scheduler)
.observeOn(Schedulers.io())
.doOnNext(word -> System.out.printf("%s uses thread %s%n", word,
Thread.currentThread().getName()))
.subscribe();
}
}
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.
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.
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.