Reputation: 3
How can i order the completion of threads? I want the below order.
Third ---> Second --> First --> Fourth.
What changes should i make in code. I am a new starter. Also please elaborate about thread priority and join. Can i call join() on two threads like thread3 waits for thread2 to complete.
class TJoin implements Runnable {
Thread tj;
String tname;
int tint, tloop;
public TJoin(String name, int time, int loop) {
tj = new Thread(this, name);
tint = time;
tloop = loop;
tj.start();
}
public void run() {
System.out.println("\n\t\t\t\t" + tj.getName() + " starts now.");
for (int j = 0; j < tloop; j++) {
System.out.println("\n" + tj.getName() + " running.");
try {
Thread.sleep(tint * 1000);
} catch (InterruptedException e) {
e.getMessage();
}
}
System.out.println("\n\t\t\t\t" + tj.getName() + " ends now.");
}
}
public class ThreadJoin {
public static void main(String[] args) {
System.out.println("\n\t\t\t\t" + Thread.currentThread().getName().toUpperCase() + " starts now.");
TJoin tj1 = new TJoin("First", 1, 15);
tj1.tj.setPriority(Thread.NORM_PRIORITY + 1);
TJoin tj2 = new TJoin("Second", 1, 15);
tj2.tj.setPriority(Thread.NORM_PRIORITY);
TJoin tj3 = new TJoin("Third", 1, 15);
tj3.tj.setPriority(Thread.MIN_PRIORITY);
TJoin tj4 = new TJoin("Fourth", 1, 15);
tj4.tj.setPriority(Thread.MAX_PRIORITY);
for (int j = 0; j < 5; j++) {
System.out.println("\n" + Thread.currentThread().getName() + " running.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.getMessage();
}
}
try {
tj2.tj.join();
tj3.tj.join();
tj1.tj.join();
tj4.tj.join();
} catch (InterruptedException e) {
e.getMessage();
}
System.out.println("\n\t\t\t\tMAIN thread ends now.");
}
}
Upvotes: 0
Views: 61
Reputation: 27190
Any time you want a sequence of things to happen, one after the other, in a particular order, you'll need to use one thread to make those things happen in that order.
So, say you have four threads running, and you want the four threads to terminate in a particular order. I don't know why you would want that, but here is how it could be done:
You are going to have to write each thread so that it does whatever it does, and then it waits for permission to die.
class MyTask implements Runnable {
private final Semaphore permissionToDie = new Semaphore(0);
public void grantPermissionToDie() {
permissionToDie.release();
}
@Override
public void run() {
doWhatever();
permissionToDie.acquire();
}
}
Then, in your main thread, you will grant each thread permission to die, and then wait for it to die (i.e., join()
it) before granting permission to the next thread.
public void main(...) {
MyTask tj1 = new Thread(new MyTask());
MyTask tj2 = new Thread(new MyTask());
MyTask tj3 = new Thread(new MyTask());
MyTask tj4 = new Thread(new MyTask());
tj1.start();
tj2.start();
tj3.start();
tj4.start();
...
t3.grantPermissionToDie();
t3.join();
t2.grantPermissionToDie();
t2.join();
t1.grantPermissionToDie();
t1.join();
t4.grantPermissionToDie();
t4.join();
}
Upvotes: 2
Reputation: 43867
Thread priority is pretty irrelevant for finish order. It can control the order if your work queue is long enough as the higher priority threads will move through the queue faster but typically if you need this kind of control you have the threads join on each other. For example, the following snippet will always have thread one end before thread two ends.
public static class JoinTask implements Runnable {
private Thread threadToWaitOn;
public JoinTask(Thread threadToWaitOn) {
this.threadToWaitOn = threadToWaitOn;
}
public void run() {
while(thereIsWork()) {
doWork();
}
if(threadToWaitOn != null) {
threadToWaitOn.join();
}
}
}
public static void main(String [] args) {
Thread threadOne = new Thread(new JoinTask(null));
Thread threadTwo = new Thread(new JoinTask(threadOne));
threadTwo.join();
}
Another option is to use a wait object or condition variable.
public static class MyCondition {
private boolean conditionMet;
public synchronized void markConditionMet() {
conditionMet = true;
notifyAll();
}
public synchronized void waitOnCondition() {
while(!conditionMet) {
wait();
}
}
}
public static class JoinTask implements Runnable {
private MyCondition onExitSignalThis;
private MyCondition onExitWaitOnThis;
public JoinTask(MyCondition onExitSignalThis, MyCondition onExitWaitOnThis) {
this.onExitWaitOnThis = onExitWaitOnThis;
this.onExitSignalThis = onExitSignalThis;
}
public void run() {
while(thereIsWork()) {
doWork();
}
if(onExitWaitOnThis != null) {
onExitWaitOnThis.waitOnCondition();
}
if(onExitSignalThis != null) {
onExitSignalThis.markConditionMet();
}
}
}
public static void main(String [] args) {
MyCondition condition;
Thread threadOne = new Thread(condition, null);
Thread threadTwo = new Thread(null, condition);
threadTwo.join();
}
In a real world example the naming and distribution of the condition objects may make more sense. For example, there might be an "initialization" phase which has to happen before worker threads start working. The initializer thread would signal the completion of the initialization phase and the worker threads would wait for the signal before beginning work.
Upvotes: 0