Singleton with Java multithreading app - java

Briefly, I want to click on a button to run a background task (separated thread). I faced two problems:
What if user click many times on that button ==>Many thread will be
created.
Even if I use Singleton mechanism, I face another problem which is the fact that only one time that instance will be created even though after task accomplishes, user can't anymore re-run the process (second click on the button).
My class:
package mypack.check;
public class RunnableCheck implements Runnable {
private Thread t;
private static RunnableCheckFeeders instance;
public RunnableCheckFeeders getDefault() {
if (instance == null) {
instance = new RunnableCheckFeeders();
}
return instance;
}
#Override
public void run() {
//What the thread is supposed to do...
}
public void start() {
if (t == null) {
t = new Thread(this, "My task");
t.start();
}
}
}
In the caller class:
RunnableCheckFeeders.getDefault().start();
I tried with Synchronized methods but in vain, any proposition is welcome.

I suggest you use an ExecutorService.
enum RunOne {; // no instances
static final ExecutorService service = Executors.newSingleThreadedExecutor();
static Future last = null;
static synchronized void run(Runnable run) {
if (last != null && !last.isDone()) return;
last = service.submit(run);
}
}
This will submit a new task only if there is not already one running. It won't create more than one thread but you can submit tasks after a previous one finishes. You can call service.shutdown() to stop the service.

Your start method doesn't guarantee that only one "my task" thread will be created, even if there is only one instance of RunnableCheck: because the checking of the thread reference and subsequent assignment is not atomic, it is possible for two threads to be created and started if both happen to evaluate t == null to true at the same time (or, at least, a second thread can evaluate it to true before the first thread was able to assign a non-null value to t).
You can guard for this by:
Making the start method synchronized, so multiple threads cannot run the method at the same time;
Add an AtomicBoolean to record if the thread has been created/started. By updating the value of this flag atomically, it is not possible for two threads to set it to true, and thus impossible for two new Threads to be created and started:
private final AtomicBoolean started = new AtomicBoolean();
private Thread t;
public void start() {
if (!started.compareAndSet(false, true)) {
return;
}
t = new Thread(this, "My task");
t.start();
}

When a user clicks multiple times then do you want the event to happen multiple times, or just the once? If multiple times, you don't want a singleton, but rather to create a queue of work.
You can do this in one of two ways, the first is to use a a want a thread pool, likely using one from the ExecutorService.
Your second option is to have a single queue reading from a queue and a single thread reading from the queue.
If you want the event to only happen the once then you need to disable the button until it is completed, make start synchronized so only one thread can call it at a time and then set t to null once the thread finishes (i.e. the last item in run()).

Related

Defining a thread id to a object and interrupt

I have threads dedicated to users on a system, and I want to be able to stop them individually, do I store the ID of the thread with the userdata at creation and then call an interrupt? or can I somehow add the thread to my user objects and just call it like myuser.mythread.interrupt(); or is this whishing for magic?
Currently I can stop them all and restart without the thread I want.
But that is a time consuming task and also triggers a lag where users must wait.
Update, can this be an answer?
if(delete==true) {
if (Thread.currentThread().getId() == deleteId) {
Thread.currentThread().interrupt();
delete=false;
}
}
Update
I managed to find a way to use myuser.mythread.interrupt();
Or sort of..
I added the thread as a sub class to the user class and created a method in the user class to start and interrupt, now i can start and stop threads with
online.get(1).hellos();
online.get(1).hellosStop();
Instead of having to create a reference and keeping track of anything else than the user objects.
Update (regarding accepted answer, using the id as a reference I could do it this way)
public class MyRunnable implements Runnable {
private boolean runThread = true;
#Override
public void run() {
try {
while (runThread) {
if(delete==true) {
if (Thread.currentThread().getId() == deleteId) {
Thread.currentThread().interrupt();
delete=false;
}
}
Thread.sleep(5);
}
}
catch (InterruptedException e) {
// Interrupted, no need to check flag, just exit
return;
}
}
}
You can just store the Thread reference, perhaps in a WeakReference so that the thread will go away if it exits on its own.
But you can also have the Thread check an AtomicBoolean (or volatile boolean) every now and then to see if it was interrupted, that way you don't need a reference to the thread.
Note though that stopping threads in Java is not possible without cooperation from the thread you want to stop. It doesn't matter if you use interrupt or a boolean that it checks, in both cases it is up to the thread to check these flags (interrupt just sets a flag) and then perform some action like exiting.
Update
A sample interruptable thread class:
public class MyRunnable implements Runnable {
private final AtomicBoolean stopFlag;
public MyRunnable(AtomicBoolean stopFlag) {
this.stopFlag = stopFlag;
}
#Override
public void run() {
try { // Try/Catch only needed if you use locks/sleep etc.
while (!stopFlag.get()) {
// Do some work, but remember to check flag often!
}
}
catch (InterruptedException e) {
// Interrupted, no need to check flag, just exit
return;
}
}
}
The best approach is to save the Thread reference and make it available to the code that needs to interrupt it.
It is technically possible (for a non-sandboxed application) to traverse the tree of all of the JVM's existing threads testing each one. However, that is expensive and doesn't scale. And if you can store or pass the id of a thread, then you should be able to store or pass the Thread reference instead.
It is also technically possible to create your own WeakHashMap<Long, Thread> and use that to map thread ids to threads. But the same argument applies ....
You ask if this is a solution:
if (delete) {
if (Thread.currentThread().getId() == deleteId) {
Thread.currentThread().interrupt();
delete = false;
}
}
No it isn't. Or more precisely, it will only "work" in the case where the thread is interrupting itself. In other cases, the target thread won't be interrupted.
Depending on your use-case, another way to do this could be to use an ExecutionService rather than bare threads. The submit methods return a Future object that represents the submitted task. The object has a cancel(...) method that can be used to cancel the task, either before it runs, or by interrupting the running thread.

Notify multiple threads periodically

I'm working on a project that uses primitive Java concurrent structures such as wait(), notify(), notifyAll(), Thread.run(), synhronized etc.
On my project, there are multiple threads (a extension of Thread class) who will get an object from a queue periodically. Thus, I use a Timer class which has an inner TimerTask class.
My problem is that, I could not get how to make other threads wake up periodically. My main class is not these threads or timer classes. Thus I call their run from another class. I could not figure out how to make these threads wait and notify for one time per 100 miliseconds. My timer class is:
public class Controller extends Timer{
int counter;
TimerTask task;
final Controller c = this;
public class PeriodicTime extends TimerTask {
#Override
public void run() {
if(counter > 0) {
//do some stuff to wake up threads
}
counter++;
}
}
Controller () {
super ();
this.task = new PeriodicTime();
counter = 0;
this.schedule(task, 300, 100);
}
}
And my thread class is:
public class Element extends Thread {
public void run() {
// do something to get an object from another class (a queue)
}
}
Now, i'm really confused how to make periodic releasing to the thread class. I even could not get whether to use wait()/notify() or not.
As I told before, i'll create multiple Element class. They will work synchronized. Then, what should I do?
Make a list of Objects that will represent mutexes, Each Element thread will get one mutex from the list, while the timer task gets the list.
TimerTask calls notify() on every mutex object when the time period expires. This wakes up the Element threads.
Element threads process data from queue and when they are done they each call wait() on their mutex object.
Now you need thread safety built into the queue since there are multiple consumers, but not the blocking logic since it is handled by the TimerTask.
Also, if I understood you correctly, you want Elements put something back to queue as they process the data. For that you can use an auxilary queue that you can drain into the first one after elements are done or you can just swap them (This is done by TimerTask and requires an atomic counter that will get incremented when Element wakes up and decremented when it goes to sleep). Alternatively, you can use a "stop" value that you can put into queue just before you wake up Elements, and make them work until they reach it. For N element threads you would need to put N stop values so all of them get the message.
How to use mutexes:
List<Object> mutexList;
//initialize the list with plain Objects. You just need them to be separate instances.
....
//When creating Element threads add one object from the list to each Element.
....
//in Element code
public class Element extends Thread {
//This is one element from the list
private Object mutex;
public void run() {
// do something to get an object from another class (a queue)
//....
synchronized(mutex){
mutex.wait();
}
}
}
// in timerTask code
public class PeriodicTime extends TimerTask {
List<Object> mutexList;
#Override
public void run() {
if(counter > 0) {
//do some stuff to wake up threads
for(Object mutex:mutexList){
mutex.notify();
}
}
counter++;
}
}

Safe way to stop Java thread

Can anyone explain to me why the first thread doesn't work and the second works perfectly:
public class Test {
public static void main(String args[]) throws InterruptedException {
TestThread1 t1 = new TestThread1();
TestThread2 t2 = new TestThread2();
t1.startThread();
t2.start();
Thread.sleep(4000);
t1.stopThread();
t2.stopThread();
}
}
class TestThread1 extends Thread {
private volatile TestThread1 thread;
public void startThread() {
thread = new TestThread1();
thread.start();
}
public void run() {
while (thread != null) {
System.out.println("RUNNING 1 ...");
}
}
public void stopThread() {
thread = null;
}
}
class TestThread2 extends Thread {
private volatile boolean finished = false;
public void run() {
while (!finished) {
System.out.println("RUNNING 2 ...");
}
}
public void stopThread() {
finished = true;
}
}
When I debug inside TestThread1 class: Inside startThread, the thread member is filled (so it is not null), inside run, thread member is null!!! And finally, inside stopThread, the thread member is not null!!!
Can anyone explain to me what is happening here?
Here, you have two instances of TestThread1 t1:
One is stored into your t1 local variable (in your main method).
One is stored into your thread instance variable (of t1).
t1 is never started, t1.thread is.
t1.stopThread() sets t1.thread to null, but it doesn't affect t1.thread.thread.
Since you're starting t1.thread, its run method is using t1.thread.thread:
This is never set to anything (so it's using null).
Calling t1.stopThread() like you do would only set t1.thread to null, which wouldn't affect t1.thread.thread.
More generally, you can't just "kill" a thread as such, but you can implement tests within the method to tell it to return under certain circumstances. What you've done with your second test is closer to this (using while (!finished) { ... } with a volatile variable).
I wouldn't limit the test to finished. It's also useful to test whether the thread was interrupted, in particular because if you run your runnables within an ExecutorService shutdownNow() will try to interrupt them (see this question).
I'd use while (!finished && !Thread.currentThread().isInterrupted()) { ... }.
(Note the difference between Thread.currentThread().isInterrupted() and Thread.interrupted(): they may seem similar, but the latter will also reset the status, which you might not want.)
Depending on what's within your loop (or whether there is a loop at all), you may want to use something like if (finished || Thread.currentThread().isInterrupted()) { return; } at various strategic points, where it makes sense.
There is two TestThread1 object being created, one is started and the other is stopped.
I suggest not extending Thread and instead wrapping your Runnable once.
TestThread1 t1 = new TestThread1();
t1.startThread();
This will simply call method startThread() on object t1. Inside this method you are creating a new Thread.
thread = new TestThread1();
thread.start();
But for this Thread thread instance variable is null(It is not null for t1).
So in both cases thread variable should be null.
Because in your main method you create a Thread1 Object. You then run startThread which creates a different Thread1 object inside the first one and sets it to the field thread. You then start the second object which didn't have its own thread field initialized. When run method is run on the second object the condition is false and the while loop doesn't start.
Your object hierarchy looks something like this
t1 (Thread1) {
thread(Thread1): {
thread: null;
run() {
while (thread != null) {...} // this is the method that is run - thread is null here since you never initialized it
}
};
startThread() {} // calls the run method on the nested thread object above
run() {
while (thread != null) {...} // this method is not run since t1.start() is never called in main()
}
}
in your case,
t2.start();
is calling run method directly, it is not creating thread inside startThread method.
so t1.stopThread() makes the volatile thread inside Thread1 class null. so you are getting like that.
solution
use
t1.startThread();
t2.startThread();
instead of
t1.startThread();
t2.start();
which makes 2 threads to create separate threads inside that method.
if you want a single thread of Thread1 then use runnable interface and create 2 threads and call startThread respectively rather than creating extra threads inside main.

Given two Java threads, stop one thread when one of them finishes

I'm looking for a clean design/solution for this problem: I have two threads, that may run as long as the user wants to, but eventually stop when the user issues the stop command. However if one of the threads ends abruptly (eg. because of a runtime exception) I want to stop the other thread.
Now both threads execute a Runnable (so when I say 'stop a thread' what I mean is that I call a stop() method on the Runnable instance), what I'm thinking is to avoid using threads (Thread class) and use the CompletionService interface and then submit both Runnables to an instance of this service.
With this I would use the CompletionService's method take(), when this method returns I would stop both Runnables since I know that at least one of them already finished. Now, this works, but if possible I would like to know of a simpler/better solution for my case.
Also, what is a good solution when we have n threads and as soon as one of them finishes to stop execution of all the others ?
Thanks in advance.
There is no Runnable.stop() method, so that is an obvious non-starter.
Don't use Thread.stop()! It is fundamentally unsafe in the vast majority of cases.
Here are a couple of approaches that should work, if implemented correctly.
You could have both threads regularly check some common flag variable (e.g. call it stopNow), and arrange that both threads set it when they finish. (The flag variable needs to be volatile ... or properly synchronized.)
You could have both threads regularly call the Thread.isInterrupted() method to see if it has been interrupted. Then each thread needs to call Thread.interrupt() on the other one when it finishes.
I know Runnable doesn't have that method, but my implementation of Runnable that I pass to the threads does have it, and when calling it the runner will finish the run() method (something like Corsika's code, below this answer).
From what I can tell, Corsika's code assumes that there is a stop() method that will do the right thing when called. The real question is how have you do implemented it? Or how do you intend to implement it?
If you already have an implementation that works, then you've got a solution to the problem.
Otherwise, my answer gives two possible approaches to implementing the "stop now" functionality.
I appreciate your suggestions, but I have a doubt, how does 'regularly check/call' translate into code ?
It entirely depends on the task that the Runnable.run() method performs. It typically entails adding a check / call to certain loops so that the test happens reasonably often ... but not too often. You also want to check only when it would be safe to stop the computation, and that is another thing you must work out for yourself.
The following should help to give you some ideas of how you might apply it to your problem. Hope it helps...
import java.util.*;
public class x {
public static void main(String[] args) {
ThreadManager<Thread> t = new ThreadManager<Thread>();
Thread a = new MyThread(t);
Thread b = new MyThread(t);
Thread c = new MyThread(t);
t.add(a);
t.add(b);
t.add(c);
a.start();
b.start();
c.start();
}
}
class ThreadManager<T> extends ArrayList<T> {
public void stopThreads() {
for (T t : this) {
Thread thread = (Thread) t;
if (thread.isAlive()) {
try { thread.interrupt(); }
catch (Exception e) {/*ignore on purpose*/}
}
}
}
}
class MyThread extends Thread {
static boolean signalled = false;
private ThreadManager m;
public MyThread(ThreadManager tm) {
m = tm;
}
public void run() {
try {
// periodically check ...
if (this.interrupted()) throw new InterruptedException();
// do stuff
} catch (Exception e) {
synchronized(getClass()) {
if (!signalled) {
signalled = true;
m.stopThreads();
}
}
}
}
}
Whether you use a stop flag or an interrupt, you will need to periodically check to see whether a thread has been signalled to stop.
You could give them access to eachother, or a callback to something that had access to both so it could interrupt the other. Consider:
MyRunner aRunner = new MyRunner(this);
MyRunner bRunner = new MyRunner(this);
Thread a = new Thread(aRunner);
Thread b = new Thread(brunner);
// catch appropriate exceptions, error handling... probably should verify
// 'winner' actually is a or b
public void stopOtherThread(MyRunner winner) {
if(winner == aRunner ) bRunner .stop(); // assumes you have stop on class MyRunner
else aRunner.stop();
}
// later
a.start();
b.start();
// in your run method
public void run() {
// la de da de da
// awesome code
while(true) fork();
// other code here
myRunnerMaster.stopOtherThread(this);
}

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