Waiting for a subset of threads in a Java ThreadPool - java

Let's say I have a thread pool containing X items, and a given task employs Y of these items (where Y is much smaller than X).
I want to wait for all of the threads of a given task (Y items) to finish, not the entire thread pool.
If the thread pool's execute() method returned a reference to the employed thread I could simply join() to each of these Y threads, but it doesn't.
Does anyone know of an elegant way to accomplish this? Thanks.

You can use a CyclicBarrier and have each thread wait only when it is of type Y. For example.
ExecutorService executor = Executors.newFixedThreadPool(X.size);
public void executeAllAndAwaitCompletion(List<? extends Y> myRunnableY){
final CyclicBarrier barrier = new CyclicBarrier(myRunnable.size()+1);
for(final Y y : myRunnableY){
executor.submit(new Runnable(){
public void run(){
y.run();//for the sake of this example y has a run method
barrier.await();
}
});
}
barrier.await();
}
So each thread that is running type Y will wait until all those Y's have completed. Note you have to add 1 to the barrier size to account for the initially executing thread to wait also.
Also Note: If Michael Borgwardt's example works for you that would be best. However, if you need the thread pool, for each thread that is running Y to not run any other non-Y's then my solution would be the only way you can do it. Future.get() will only block the calling thread, and when the thread pool finishes Y's execution it will then pick up some other (possibly non-Y) task.

Instead of execute()ing Runnables, just invokeAll() some Callables - then you get a Future for each on which you can call get(), which blocks until the task is finished.

You should use a CompletionService which is used for exactly this purpose.
Create Executor
Create ExecutorCompletionService using the Executor
Submit tasks via the CompletionService
Use take or poll on the CompletionService to wait for the tasks to finish
Repeat until all the tasks you submitted have finished
Done
You can share an Executor with something else, just create the CompletionService over the top and use it for your specific tasks.

Create CountDownLatch with Y as count and do latch.countDown() in each of Y tasks. In the end latch.await() will ensure that all of the Y tasks are completed.

Related

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;
}

How can I implement FIFO queue of threads?

How can I implement FIFO queue of threads(tasks to do) and executing the threads one by one?
I mean for example, take the first thread and run it, and the second must wait for the end of execution of the first thread.
At the same time I must be able to add threads(tasks) to the queue.
Create a FixedThreadPool with only one thread and submit tasks to it. They will be executed one after the other, like in a FIFO queue:
ExecutorService es = Executors.newFixedThreadPool(1); // one thread only
// ...
for(Runnable r : myRunnables) {
es.submit(r);
}
As Vakh said, use an ExecutorService to run the threads, however I would recommend using a SingleThreadExecutor. The SingleThreadExectutor is guaranteed to execute threads sequentially because unlike a FixedThreadPool it can not be reconfigured to use a different number of threads.
ExecutorService es = Executors.newSingleThreadExecutor(); // one thread only
// ...
for(Runnable r : myRunnables) {
es.submit(r);
}
You can also call Thread.join() to tell the current thread to block exectution until the other thread dies.
Thread t = new Thread(myRunnable);
t.join(); //Wait until t dies
There are variations of join which will set a maximum wait time
if you want all your threads to run at the same time but you don't want them to use a specific resource or task, then you can use Synchronized Methods

java multithreading for synchronization between tasks

I have a requirement in multi-threaded environment in java. The problem is like;
I have suppose 10 different task, and I want to assign all these 10 task to 10 different threads. Now the finish time for these tasks could be different. And there is some finishing or clearance task which should be performed when all these 10 threads are finished. In other words i need to wait until all threads are finished and then only I can go ahead with my further code execution.
Please let me know if any more details required here.
Thansk,
Ashish
Sounds like an ideal job for CountDownLatch.
Initialize it with 10 counts and when each thread finishes its job, it counts down one.
When all 10 threads have finished, the CountDownLatch will let the original thread run, and it can perform the cleanup.
And fire up an ExecutorService with 10 fixed threads to run the tasks.
CyclicBarier (JDK java.util.concurrent) of size 10 is perfect solutuon for you. With CyclicBarier you can wait for 10 threads. If all t hreads achieve barier then you can go further.
Edit: CyclicBarier is almost the same as CountDownLatch but you can reuse barier invoking reset() method.
Whilst CountDownLatch and CyclicBarier do the job of synchronizing multiple threads and performing one action when all threads reach the required point, they require all tasks to actively use this feature. If you are interested in the finishing of the entire task(s) only, the solution can be much simpler: add all tasks to a Collection and use the invokeAll method of an ExecutorService which returns when all tasks have been completed. A simple example:
Callable<Void> simpleTask=new Callable<Void>() {
public Void call() {
System.out.println("Performing one job");
return null;
}
};
List<Callable<Void>> list = Collections.nCopies(10, simpleTask);
ExecutorService es=Executors.newFixedThreadPool(10);
es.invokeAll(list);
System.out.println("All completed");
If each thread terminates after it is finished, you could just use the join() statement. A simple example can be found in the Essential Java Tutorials.
ArrayList<Thread> myThreads = new ArrayList<Thread>();
for (int i = 0; i < 10; i++){
//MyTaskRunnable is a Runnable with your logic
Thread t = new Thread(new MyTaskRunnable());
myThreads.add(t);
}
for(Thread t : myThreads){
t.start();
}
//here all threads are running
for(Thread t : myThreads){
t.join();
}
//here all threads have terminated
Edit:
The other answers all have their merits and are very useful in practice, the join() is however the most basic of the constructs. The CyclicBarrier and CountDownLatch versions allow your threads to continue running after reaching the synchronization point, which can be necessary in some cases. The ExecutorService is more suited to many tasks needing to be executed on a fixed number of threads (aka a thread pool), to create an ExecutorService for just 10 tasks is a bit drastic.
Finally, if you are new to learning Java or are taking a course on concurrency, you should try out all the variants and see what they do. The join is the most basic of these constructs and will help you understand you what is going on. Also it is the basic model supported by most other languages.

Executor in java

I was trying to run ExecutorService object with FixedThreadPool and I ran into problems.
I expected the program to run in nanoseconds but it was hung. I found that I need to use Semaphore along with it so that the items in the queue do not get added up.
Is there any way I can come to know that all the threads of the pool are used.
Basic code ...
static ExecutorService pool = Executors.newFixedThreadPool(4);
static Semaphore permits = new Semaphore(4);
try {
permits.acquire();
pool.execute(p); // Assuming p is runnable on large number of objects
permits.release();
} catch ( InterruptedException ex ) {
}
This code gets hanged and I really don't know why. How to know if pool is currently waiting for all the threads to finish?
By default, if you submit more than 4 tasks to your pool then the extra tasks will be queued until a thread becomes available.
The blog you referenced in your comment uses the semaphore to limit the amount of work that can be queued at once, which won't be a problem for you until you have many thousands of tasks queued up and they start eating into the available memory. There's an easier way to do this, anyway - construct a ThreadPoolExecutor with a bounded queue.* But this isn't your problem.
If you want to know when a task completes, notice that ExecutorService.submit() returns a Future object which can be used to wait for the task's completion:
Future<?> f = pool.execute(p);
f.get();
System.out.println("task complete");
If you have several tasks and want to wait for all of them to complete, either store each Future in a list and then call get() on each in turn, or investigate ExecutorService.invokeAll() (which essentially does the same but in a single method call).
You can also tell whether a task has completed or not:
Future<?> f = pool.execute(p);
while(!f.isDone()) {
// do something else, task not complete
}
f.get();
Finally, note that even if your tasks are complete, your program may not exit (and thus appears to "hang") if you haven't called shutdown() on the thread pool; the reason is that the threads are still running, waiting to be given more work to do.
*Edit: sorry, I just re-read my answer and realised this part is incorrect - ThreadPoolExecutor offers tasks to the queue and rejects them if they aren't accepted, so a bounded queue has different semantics to the semaphore approach.
You do not need the Semaphore.
If you are hanging it is probably because the threads are locking themselves elsewhere.
Run the code in a Debuger and when it hangs pause it and see what the threads are doing.
You could change to using a ThreadPoolExecutor. It contains a getActiveCount() method which returns an approximate count of the active threads. Why it is approximate I'm not sure.

Collecting Return Values from Launched Threads? [latest Java]

I'm looking for the simplest, most straightforward way to implement the following:
main starts and launches 3 threads
all 3 tasks process and end in a resulting value (which I need to return somehow?)
main waits (.join?) on each thread to ensure they have all 3 completed their task
main somehow gets the value from each thread (3 values)
Then the rest is fairly simple, processes the 3 results and then terminates...
Now, I've been doing some reading and found multiple ideas, like:
Using Future, but this is for asynch, is this really a good idea when the main thread needs to block waiting for all 3 spawned threads to finsih?
Passing in an object (to a thread) and then simply having the thread "fill it" with the result
Somehow using Runnable (not sure how yet).
Anyways - what would be the best, and simplest recommended approach?
Thanks,
List<Callable<Result>> list = ... create list of callables
ExecutorService es = Executors.newFixedThreadPool(3);
List<Future<Result>> results = es.invokeAll(list);
ExecutorService.invokeAll method will return only after all tasks (instances of Callable) finished, either normally or by throwing exception.
For details see ExecutorService (mainly its invokeAll method), Executors, Callable.
You could also use a Semaphore from java.util.concurrent.
Create a new Semaphore with 1 - #threads permits and have main call acquire() on the Semaphore.
When each of the threads you have created has finished it's work, get it to call the release() method.
As you have created a Semaphore with a negative number of permits the call to acquire() will block until this number becomes positive. This will not happen until all of your threads have released a permit on the Semaphore.

Categories