How can I tell that threads in ThreadPoolExecutor are done? - java

I am writing code where I need to make sure that no threads are currently running in a thread pool before I commit results (to avoid losing data I should have put in the commit). For that, I'm using:
while (_executor.getActiveCount() > 0)
{
try
{
Thread.sleep(10); // milliseconds
}
catch (InterruptedException e)
{
// OK do nothing
}
}
But a colleague pointed out in review that the doc for getActiveCount states:
Returns the approximate number of threads that are actively
executing tasks.
So, is there a risk I would get out of the while loop while there are still active threads in the pool? If so, what would be the correct way to wait for all my worker threads to be done?
Edit: To give some more context: this is an online system, where the task that contains the executor service is left running indefinitely. Work comes in via a messaging system, is put on a thread in the executor, which doesn't need any synchronization, and works come out into another queue for the messaging system. I don't want to kill the executor to wait for completion of tasks.

You might want to consider using a CompletionService (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html).
A CompletionService wraps an ExecutorService and returns a Future when tasks are submitted. By maintaining a list of these Futures, you can see if the jobs that you're waiting on have completed. It also has the additional advantage that you can have others use the same ExecutorService since you have some means of accounting,

_executor.awaitTermination(); should do the job. Now, it won't actually wait for the threads to shutdown, but rather it would wait for all available tasks to terminate.
You could also provide keepAliveTime to a thread pool constructor to instantly terminate idle threads:
ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

To notify a thread that it should clean up and terminate, use the interrupt method.
t.interrupt();
and it is good to print or have log of your errors from catch block.

When tasks are submitted to the executor, they return Futures, which indicate when they complete. That is the preferred mechanism to use.
You can use JDK ExecutorService shutdown/awaitTermination.

Use case: need to cleanup thread-locals in pool threads upon their completion and this cleanup can take long (e.g. connection close). Only after that the main thread can continue.
A worker thread can register itself in some collection. For that override start() and run() and pass a custom thread factory to ThreadPoolExecutor:
class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(final Runnable r) {
return new MyThread(r);
}
...
class Some {
void waitAllThreads() {
Thread worker;
while ((worker = workerThreads.poll()) != null) {
worker.join();
}
}
...
class MyThread extends Thread {
#Override
public synchronized void start() {
if (getState() == State.NEW) {
some.workerThreads.offer(this);
}
super.start();
}
#Override
public void run() {
try {
super.run();
} finally {
some.workerThreads.remove(this);
}
}
...

Related

Can the number of tasks submitted to a thread pool be limited

I have a scenario that I have a thread pool with 100 threads for example.
There are 10 jobs, each of these jobs can send 1..n tasks to the thread pool.
If I just submit them directly, they will job compete for the threads in the pool.
Is there any way I can say something like:
Job 1 can submit a maximum of 5 tasks to the thread pool at the same time and have to wait for one of them to complete before sending the next one.
I know I can do this if I have separate thread pools for each job. But these jobs are incoming requests that appear and dissapear on the fly. It might not be good to dynamically create thread pools this way.
Can I achieve the above using one single big thread pool?
You can create your own ExecutorService, something like:
class LimitingExecutorService implements ExecutorService {
private final ExecutorService delegate;
private final Semaphore semaphore;
LimitingExecutorService(ExecutorService delegate, int limit) {
this.delegate = delegate;
this.semaphore = new Semaphore(limit);
}
Now, you can implement the methods to delegate the call to delegate, but checking that the semaphore can be acquired, e.g.:
public Future<?> submit(Runnable task) {
// Or you could block.
if (!semaphore.tryAcquire()) {
throw new RejectedExecutionException(...); // Indicate that the task couldn't be submitted.
}
// Wrap task with in another runnable() that releases the semaphore (whether or not it succeeds).
try {
return delegate.submit(() -> {
try {
task.run();
} finally {
semaphore.release();
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
etc for other methods.
You will need to take care around methods like invokeAll to decide what the behavior should be: should they invoke as many as they can, or should that call only succeed if all tasks can be scheduled at that moment.
Now, each of your jobs can have their own instance of LimitingExecutorService, and they can only submit as many jobs as the semaphore's available permits allow.

Shutdown executor without knowing when it will finish all the tasks

I have a task that should wait for a condition (OpenCms startup) and then notify some listeners.
to do this I used an ExecutorService:
public void check(final ExecutorService executorService) {
executorService.submit(() -> {
waitForInitialization();
notifyListeners();
});
}
private void waitForInitialization() {
while (OpenCms.getRunLevel() < OpenCms.RUNLEVEL_4_SERVLET_ACCESS) {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
the question is how to shutdown this executor. I could use awaitTermination but I should provide a timeout which I don't know exactly. it could vary from one environment to the other.
the question is how to shutdown this executor. I could use awaitTermination but I should provide a timeout which I don't know exactly. it could vary from one environment to the other.
The question I would ask is do you need a timeout at all? Often if you know that a particular job will finish at some point I just wait for a timeout Long.MAX_VALUE – effectively forever. Other times I'll do something like:
threadPool.shutdown();
threadPool.awaitTermination(...) of some small value (maybe 10 seconds)
threadPool.shutdownNow(); to interrupt the threads
threadPool.awaitTermination(...); of Long.MAX_VALUE because I know the jobs will finish eventually
it could vary from one environment to the other.
If it could vary then maybe you should be able to calculate what a proper timeout would be for each environment?
Lastly, don't be afraid of passing in a ThreadFactory that creates daemon threads. For some jobs I shutdown() the thread-pool but never wait for them to complete because I don't care about their status so I create the threads in the pool with daemon enabled maybe using something like the following thread-factory.
/** Thread factory which sets name and optionally daemon */
public class PoolNameThreadFactory implements ThreadFactory {
private final String poolName;
private final Boolean daemon;
private final AtomicInteger threadNum = new AtomicInteger(0);
public PoolNameThreadFactory(String poolName) {
this(poolName, null);
}
public PoolNameThreadFactory(String poolName, boolean daemon) {
this(poolName, (Boolean) daemon);
}
private PoolNameThreadFactory(String poolName, Boolean daemon) {
this.poolName = poolName;
this.daemon = daemon;
}
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName(poolName + '-' + threadNum.incrementAndGet());
if (daemon != null) {
thread.setDaemon(daemon);
}
return thread;
}
}
Based on the provided information, I'd clearly recommend an event-based approach. Especially knowing that in your own code there is a call like notifyListeners(). In fact, that's the way to go.
In summary, once the precondition is met somewhere in your app, just notify the listeners of this event. In your example, the "OpenCms run level" change is typically an event. So, just go for an Observer pattern, or a pub-sub model to observe or monitor these changes.
If you modify your approach, you will not have to worry about the waiting time around the initialization, except if you wish to handle the absence of event specifically. That would be done again after some timeout, but with the advantage of not blocking an executor thread.

Java ExecutorService pause/resume a specific thread

Is there a way to use ExecutorService to pause/resume a specific thread?
private static ExecutorService threadpool = Executors.newFixedThreadPool(5);
Imagine that I want to stop the thread which as the id=0 (assuming that to each one is assigned an incremental id until the size of the threadpool is reached).
After a while, by pressing a button let's say, I want to resume that specific thread and leave all the other threads with their current status, which can be paused or resumed.
I have found on Java documentation a uncompleted version of PausableThreadPoolExecutor. But it doesn't suit what I need because it resume all the threads in the pool.
If there's no way to do it with the default implementation of the ExecutorService can anyone point me to a Java implementation for this problem?
You are on the wrong track. The thread pool owns the threads and by sharing them with your code could mess things up.
You should focus on making your tasks (passed to the threads cancellable/interruptable) and not interact with the threads owned by the pool directly.
Additionally you would not know what job is being executed at the time you try to interrupt the thread, so I can't see why you would be interested in doing this
Update:
The proper way to cancel your task submitted in the thread pool is via the Future for the task returned by the executor.
1)This way you know for sure that the task you actually aim at is attempted to be cancelled
2)If your tasks are already designed to be cancellable then your are half way there
3) Do not use a flag to indicate cancellation but use Thread.currentThread().interrupt() instead
Update:
public class InterruptableTasks {
private static class InterruptableTask implements Runnable{
Object o = new Object();
private volatile boolean suspended = false;
public void suspend(){
suspended = true;
}
public void resume(){
suspended = false;
synchronized (o) {
o.notifyAll();
}
}
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
if(!suspended){
//Do work here
}
else{
//Has been suspended
try {
while(suspended){
synchronized(o){
o.wait();
}
}
}
catch (InterruptedException e) {
}
}
}
System.out.println("Cancelled");
}
}
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newCachedThreadPool();
InterruptableTask task = new InterruptableTask();
Map<Integer, InterruptableTask> tasks = new HashMap<Integer, InterruptableTask>();
tasks.put(1, task);
//add the tasks and their ids
Future<?> f = threadPool.submit(task);
TimeUnit.SECONDS.sleep(2);
InterruptableTask theTask = tasks.get(1);//get task by id
theTask.suspend();
TimeUnit.SECONDS.sleep(2);
theTask.resume();
TimeUnit.SECONDS.sleep(4);
threadPool.shutdownNow();
}
Suggestion: Similarly to/instead of the flags you're using, create a semaphore with 1 permit (new Semaphore(1)) for each task you need to pause/unpause. At the beginning of the task's working cycle put a code like this:
semaphore.acquire();
semaphore.release();
This causes the task to acquire a semaphore permit and immediately release it. Now if you want to pause the thread (a button is pressed, for example), call semaphore.acquire() from another thread. Since the semaphore has 0 permits now, your working thread will pause at the beginning of the next cycle and wait until you call semaphore.release() from the other thread.
(The acquire() method throws InterruptedException, if your working thread gets interrupted while waiting. There is another method acquireUninterruptibly(), which also tries to acquire a permit, but doesn't get interrupted.)
One scenario could be, one wants to simulate a number of devices. Devices have functions. Altogether this collection of devices runs concurrently. And now if a thread represents a device ( or one thread for one function of a device ), one might want to control the life cycle of the device like start(), shutdown(), resume()

How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?

I am getting data from a queue server and I need to process it and send an acknowledgement. Something like this:
while (true) {
queueserver.get.data
ThreadPoolExecutor //send data to thread
queueserver.acknowledgement
I don't fully understand what happens in threads but I think this program gets the data, sends it the thread and then immediately acknowledges it. So even if I have a limit of each queue can only have 200 unacknowledged items, it will just pull as fast as it can receive it. This is good when I write a program on a single server, but if I'm using multiple workers then this becomes an issue because the amount of items in the thread queue are not a reflection of the work its done but instead of how fast it can get items from the queue server.
Is there anything I can do to somehow make the program wait if the thread queue is full of work?
How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?
Instead of an open-ended queue, you can use a BlockingQueue with a limit on it:
BlockingQueue<Date> queue = new ArrayBlockingQueue<Date>(200);
In terms of jobs submitted to an ExecutorService, instead of using the default ExecutorServices created using Executors, which use an unbounded queue, you can create your own:
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(200));
Once the queue fills up, it will cause it to reject any new tasks that are submitted. You will need to set a RejectedExecutionHandler that submits to the queue. Something like:
final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, queue);
// by default (unfortunately) the ThreadPoolExecutor will throw an exception
// when you submit the 201st job, to have it block you do:
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// this will block if the queue is full
executor.getQueue().put(r);
// check afterwards and throw if pool shutdown
if (executor.isShutdown()) {
throw new RejectedExecutionException(
"Task " + r + " rejected from " + e);
}
}
});
I think it's a major miss that Java doesn't have a ThreadPoolExecutor.CallerBlocksPolicy.
If you want the acknowledgment when the worker starts working on the task, you can make a custom ThreadFactory that sends the acknowledgment from the thread before doing the actual work. OR you can override beforeExecute of a ThreadPoolExecutor.
If you want the acknowledgment when a new worker is freed up for a new task, I think you can initialize a ThreadPoolExecutor with a SynchronousQueue and a ThreadPoolExecutor.CallerRunsPolicy, or with your own policy where the caller blocks.
first, i think your attitude is wrong because what you did in your pseudo code is busy waiting, you should read through the Concurrency tutorial from java toturial http://docs.oracle.com/javase/tutorial/essential/concurrency/
ignoring that, ill offer you a solution with the busy wait (which is not recommanded):
ExecutorService e1 = Executors.newFixedThreadPool(20);
while (true) {
if (!serverq.isEmpty() && !myq.isFull()) myq.enq(serverq.poll());
if (!myq.isEmpty()) e1.execute(myq.poll());
}
NOTES:
1.make sure your myq is synchronized, as said in the other answers. you can extend some blocking queue to make sure the synchronization is correct.
2.you implement a runnable class which does what you exepct from the server in an iteration
of service, those runnables have to get myq as a parameter to the constructor and save it as global variable.
3.myq gets the runnables, that in the end of its run method, you must make sure the runnable deletes itself from myq.
What about having a blockingPool which will not execute more than 200 tasks and wait for a task to complete before submitting 201 task. I've achieved it using semaphore in my application. You can also change the limit by passing the value to its constructor.
Only difference here from #Gray answer is that rarely any task will get rejected in this case. Semaphore will make any 201 task to wait unless a other task gets over. Nevertheless, we have rejection handler to re-submit that task to executor in case of any rejection.
private class BlockingPool extends ThreadPoolExecutor {
private final Semaphore semaphore;
public BlockingPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, int tasksAllowedInThreads){
super(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
executor.execute(r);
}
});
semaphore = new Semaphore(tasksAllowedInThreads);
}
#Override
public void execute(Runnable task){
boolean acquired = false;
do{
try{
semaphore.acquire();
acquired = true;
} catch (final InterruptedException e){
// log
}
} while (!acquired); // run in loop to handle InterruptedException
try{
super.execute(task);
} catch (final RejectedExecutionException e){
System.out.println("Task Rejected");
semaphore.release();
throw e;
}
}
#Override
protected void afterExecute(Runnable r, Throwable t){
super.afterExecute(r, t);
if (t != null){
t.printStackTrace();
}
semaphore.release();
}
}
Does this make sense!

How to know if other threads have finished?

I have an object with a method named StartDownload(), that starts three threads.
How do I get a notification when each thread has finished executing?
Is there a way to know if one (or all) of the thread is finished or is still executing?
There are a number of ways you can do this:
Use Thread.join() in your main thread to wait in a blocking fashion for each Thread to complete, or
Check Thread.isAlive() in a polling fashion -- generally discouraged -- to wait until each Thread has completed, or
Unorthodox, for each Thread in question, call setUncaughtExceptionHandler to call a method in your object, and program each Thread to throw an uncaught Exception when it completes, or
Use locks or synchronizers or mechanisms from java.util.concurrent, or
More orthodox, create a listener in your main Thread, and then program each of your Threads to tell the listener that they have completed.
How to implement Idea #5? Well, one way is to first create an interface:
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
then create the following class:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
and then each of your Threads will extend NotifyingThread and instead of implementing run() it will implement doRun(). Thus when they complete, they will automatically notify anyone waiting for notification.
Finally, in your main class -- the one that starts all the Threads (or at least the object waiting for notification) -- modify that class to implement ThreadCompleteListener and immediately after creating each Thread add itself to the list of listeners:
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed (or crashed).
Note that better would be to implements Runnable rather than extends Thread for NotifyingThread as extending Thread is usually discouraged in new code. But I'm coding to your question. If you change the NotifyingThread class to implement Runnable then you have to change some of your code that manages Threads, which is pretty straightforward to do.
Solution using CyclicBarrier
public class Downloader {
private CyclicBarrier barrier;
private final static int NUMBER_OF_DOWNLOADING_THREADS;
private DownloadingThread extends Thread {
private final String url;
public DownloadingThread(String url) {
super();
this.url = url;
}
#Override
public void run() {
barrier.await(); // label1
download(url);
barrier.await(); // label2
}
}
public void startDownload() {
// plus one for the main thread of execution
barrier = new CyclicBarrier(NUMBER_OF_DOWNLOADING_THREADS + 1); // label0
for (int i = 0; i < NUMBER_OF_DOWNLOADING_THREADS; i++) {
new DownloadingThread("http://www.flickr.com/someUser/pic" + i + ".jpg").start();
}
barrier.await(); // label3
displayMessage("Please wait...");
barrier.await(); // label4
displayMessage("Finished");
}
}
label0 - cyclic barrier is created with number of parties equal to the number of executing threads plus one for the main thread of execution (in which startDownload() is being executed)
label 1 - n-th DownloadingThread enters the waiting room
label 3 - NUMBER_OF_DOWNLOADING_THREADS have entered the waiting room. Main thread of execution releases them to start doing their downloading jobs in more or less the same time
label 4 - main thread of execution enters the waiting room. This is the 'trickiest' part of the code to understand. It doesn't matter which thread will enter the waiting room for the second time. It is important that whatever thread enters the room last ensures that all the other downloading threads have finished their downloading jobs.
label 2 - n-th DownloadingThread has finished its downloading job and enters the waiting room. If it is the last one i.e. already NUMBER_OF_DOWNLOADING_THREADS have entered it, including the main thread of execution, main thread will continue its execution only when all the other threads have finished downloading.
You should really prefer a solution that uses java.util.concurrent. Find and read Josh Bloch and/or Brian Goetz on the topic.
If you are not using java.util.concurrent.* and are taking responsibility for using Threads directly, then you should probably use join() to know when a thread is done. Here is a super simple Callback mechanism. First extend the Runnable interface to have a callback:
public interface CallbackRunnable extends Runnable {
public void callback();
}
Then make an Executor that will execute your runnable and call you back when it is done.
public class CallbackExecutor implements Executor {
#Override
public void execute(final Runnable r) {
final Thread runner = new Thread(r);
runner.start();
if ( r instanceof CallbackRunnable ) {
// create a thread to perform the callback
Thread callerbacker = new Thread(new Runnable() {
#Override
public void run() {
try {
// block until the running thread is done
runner.join();
((CallbackRunnable)r).callback();
}
catch ( InterruptedException e ) {
// someone doesn't want us running. ok, maybe we give up.
}
}
});
callerbacker.start();
}
}
}
The other sort-of obvious thing to add to your CallbackRunnable interface is a means to handle any exceptions, so maybe put a public void uncaughtException(Throwable e); line in there and in your executor, install a Thread.UncaughtExceptionHandler to send you to that interface method.
But doing all that really starts to smell like java.util.concurrent.Callable. You should really look at using java.util.concurrent if your project permits it.
Many things have been changed in last 6 years on multi-threading front.
Instead of using join() and lock API, you can use
1.ExecutorService invokeAll() API
Executes the given tasks, returning a list of Futures holding their status and results when all complete.
2.CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
3.ForkJoinPool or newWorkStealingPool() in Executors is other way
4.Iterate through all Future tasks from submit on ExecutorService and check the status with blocking call get() on Future object
Have a look at related SE questions:
How to wait for a thread that spawns it's own thread?
Executors: How to synchronously wait until all tasks have finished if tasks are created recursively?
Do you want to wait for them to finish? If so, use the Join method.
There is also the isAlive property if you just want to check it.
You can interrogate the thread instance with getState() which returns an instance of Thread.State enumeration with one of the following values:
* NEW
A thread that has not yet started is in this state.
* RUNNABLE
A thread executing in the Java virtual machine is in this state.
* BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
* WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
* TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
* TERMINATED
A thread that has exited is in this state.
However I think it would be a better design to have a master thread which waits for the 3 children to finish, the master would then continue execution when the other 3 have finished.
You could also use the Executors object to create an ExecutorService thread pool. Then use the invokeAll method to run each of your threads and retrieve Futures. This will block until all have finished execution. Your other option would be to execute each one using the pool and then call awaitTermination to block until the pool is finished executing. Just be sure to call shutdown() when you're done adding tasks.
I would suggest looking at the javadoc for Thread class.
You have multiple mechanisms for thread manipulation.
Your main thread could join() the three threads serially, and would then not proceed until all three are done.
Poll the thread state of the spawned threads at intervals.
Put all of the spawned threads into a separate ThreadGroup and poll the activeCount() on the ThreadGroup and wait for it to get to 0.
Setup a custom callback or listener type of interface for inter-thread communication.
I'm sure there are plenty of other ways I'm still missing.
I guess the easiest way is to use ThreadPoolExecutor class.
It has a queue and you can set how many threads should be working in parallel.
It has nice callback methods:
Hook methods
This class provides protected overridable beforeExecute(java.lang.Thread, java.lang.Runnable) and afterExecute(java.lang.Runnable, java.lang.Throwable) methods that are called before and after execution of each task. These can be used to manipulate the execution environment; for example, reinitializing ThreadLocals, gathering statistics, or adding log entries. Additionally, method terminated() can be overridden to perform any special processing that needs to be done once the Executor has fully terminated.
which is exactly what we need. We will override afterExecute() to get callbacks after each thread is done and will override terminated() to know when all threads are done.
So here is what you should do
Create an executor:
private ThreadPoolExecutor executor;
private int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
private void initExecutor() {
executor = new ThreadPoolExecutor(
NUMBER_OF_CORES * 2, //core pool size
NUMBER_OF_CORES * 2, //max pool size
60L, //keep aive time
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>()
) {
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
//Yet another thread is finished:
informUiAboutProgress(executor.getCompletedTaskCount(), listOfUrisToProcess.size());
}
}
};
#Override
protected void terminated() {
super.terminated();
informUiThatWeAreDone();
}
}
And start your threads:
private void startTheWork(){
for (Uri uri : listOfUrisToProcess) {
executor.execute(new Runnable() {
#Override
public void run() {
doSomeHeavyWork(uri);
}
});
}
executor.shutdown(); //call it when you won't add jobs anymore
}
Inside method informUiThatWeAreDone(); do whatever you need to do when all threads are done, for example, update UI.
NOTE: Don't forget about using synchronized methods since you do your work in parallel and BE VERY CAUTIOUS if you decide to call synchronized method from another synchronized method! This often leads to deadlocks
Hope this helps!
Here's a solution that is simple, short, easy to understand, and works perfectly for me. I needed to draw to the screen when another thread ends; but couldn't because the main thread has control of the screen. So:
(1) I created the global variable: boolean end1 = false; The thread sets it to true when ending. That is picked up in the mainthread by "postDelayed" loop, where it is responded to.
(2) My thread contains:
void myThread() {
end1 = false;
new CountDownTimer(((60000, 1000) { // milliseconds for onFinish, onTick
public void onFinish()
{
// do stuff here once at end of time.
end1 = true; // signal that the thread has ended.
}
public void onTick(long millisUntilFinished)
{
// do stuff here repeatedly.
}
}.start();
}
(3) Fortunately, "postDelayed" runs in the main thread, so that's where in check the other thread once each second. When the other thread ends, this can begin whatever we want to do next.
Handler h1 = new Handler();
private void checkThread() {
h1.postDelayed(new Runnable() {
public void run() {
if (end1)
// resond to the second thread ending here.
else
h1.postDelayed(this, 1000);
}
}, 1000);
}
(4) Finally, start the whole thing running somewhere in your code by calling:
void startThread()
{
myThread();
checkThread();
}
You could also use SwingWorker, which has built-in property change support. See addPropertyChangeListener() or the get() method for a state change listener example.
Look at the Java documentation for the Thread class. You can check the thread's state. If you put the three threads in member variables, then all three threads can read each other's states.
You have to be a bit careful, though, because you can cause race conditions between the threads. Just try to avoid complicated logic based on the state of the other threads. Definitely avoid multiple threads writing to the same variables.

Categories