最简单的做法就是通过在一个线程中join另一个线程实现,比如在T2线程中调用T1.join,这样就可以保证T1的执行顺序在T2的前面。join天生就是用来解决这类问题的,以下是代码。
package com.qingping.concurrent;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/**
* 有三个线程T1,T2,T3,怎么确保它们按顺序执行?
* 在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。
* 为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
*/
public class JoinDemo {
public static void main(String[] args) {
Thread1 thread1 =new Thread1();
thread1.start();
Thread2 thread2 =new Thread2(thread1);
thread2.start();
Thread3 thread3 =new Thread3(thread2);
thread3.start();
}
@Test
public void test() {
Thread1 thread1 =new Thread1();
thread1.start();
Thread2 thread2 =new Thread2(thread1);
thread2.start();
Thread3 thread3 =new Thread3(thread2);
thread3.start();
}
}
/**
* 线程T1由T2join启动
*/
class Thread1extends Thread {
@Override
public void run() {
System.out.println("Thread1 start sleep");
for (int i =0; i <100; i++) {
System.out.println("Thread1 " + i);
}
System.out.println("Thread1 has wakened");
}
}
/**
* 在线程2中加入线程1
*/
class Thread2extends Thread {
private Thread1thread1;
public Thread2(Thread1 thread1) {
this.thread1 = thread1;
}
@Override
public void run() {
try {
thread1.join();
System.out.println("Thread2 start sleep");
for (int i =0; i <100; i++) {
System.out.println("Thread2 " + i);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2 has wakened");
}
}
/**
* 在线程3中加入线程2
*/
class Thread3extends Thread {
private Thread2thread2;
public Thread3(Thread2 thread2) {
this.thread2 = thread2;
}
@Override
public void run() {
try {
thread2.join();
System.out.println("Thread3 start sleep");
for (int i =0; i <100; i++) {
System.out.println("Thread3 " + i);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread3 has wakened");
}
}
当时我还想过用wait和nofityAll来实现,后来发现很麻烦,wait和notifyAll需要释放锁,必须要在同步块里实现。但是既然idea已经有了,不去实现好像很难受,这里我也给贴出来。刚开始我想用临界区来实现锁的获取和释放,后来发现会报错,看了半天我也没明白为什么。所以不得已只能把wait和nofityAll方法放在WaitDemo中,我发现这样写代码反而更加整洁优雅了。
package com.qingping.concurrent;
import java.util.concurrent.TimeUnit;
/**
* 有三个线程T1,T2,T3,怎么确保它们按顺序执行?
* 可以通过等待--唤醒的方式来确保他们按顺序执行。
*/
public class WaitDemo {
private int i =0;
public static void main(String[] args) {
WaitDemo waitDemo =new WaitDemo();
ThreadA threadA =new ThreadA(waitDemo);
threadA.start();
ThreadB threadB =new ThreadB(waitDemo);
threadB.start();
ThreadC threadC =new ThreadC(waitDemo);
threadC.start();
}
/**
* 工作完成,i++,唤醒所有wait的线程。
*/
public synchronized void notifyAllThread() {
i++;
notifyAll();
}
/**
* 线程B等待线程A完成
* @throws InterruptedException
*/
public synchronized void waitForA()throws InterruptedException {
while (i <=0) {
wait();
}
}
/**
* 线程C等待线程B完成
* @throws InterruptedException
*/
public synchronized void waitForB()throws InterruptedException {
while (i <=1) {
wait();
}
}
}
/**
* 线程A
*/
class ThreadAextends Thread {
private WaitDemowaitDemo;
public ThreadA(WaitDemo waitDemo) {
this.waitDemo = waitDemo;
}
@Override
public void run() {
try {
System.out.println("ThreadA start sleep");
TimeUnit.MILLISECONDS.sleep(3000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadA has wakened");
waitDemo.notifyAllThread();
}
}
/**
* 线程B
*/
class ThreadBextends Thread {
private WaitDemowaitDemo;
public ThreadB(WaitDemo waitDemo) {
this.waitDemo = waitDemo;
}
@Override
public void run() {
try {
waitDemo.waitForA();
System.out.println("ThreadB start sleep");
TimeUnit.MILLISECONDS.sleep(2000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadB has wakened");
// 线程B工作完成,i++,唤醒所有wait的线程。
waitDemo.notifyAllThread();
}
}
/**
* 线程C
*/
class ThreadCextends Thread {
private WaitDemowaitDemo;
public ThreadC(WaitDemo waitDemo) {
this.waitDemo = waitDemo;
}
@Override
public void run() {
try {
waitDemo.waitForB();
System.out.println("ThreadC start sleep");
TimeUnit.MILLISECONDS.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadC has wakened");
waitDemo.notifyAllThread();
}
}