先说一下为什么会有这样的要求,如果是简略的要求按程序执行代码,间接一行行写下来就行了。然而接口调用咱们个别都放在工作线程外面,而且有时候须要拿一个接口返回的参数去申请另一个接口,这就须要控制线程按某种程序执行。

办法1:join()

public class A1 extends Thread {    @Override    public void run() {        try {            System.out.println("--- thread A1 start ---");            sleep((long) (Math.random() * 30));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("--- thread A1 end ---");    }}public class A2 extends Thread {    @Override    public void run() {        try {            System.out.println("--- thread A2 start ---");            sleep((long) (Math.random() * 30));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("--- thread A2 end ---");    }}public class A3 extends Thread {    @Override    public void run() {        try {            System.out.println("--- thread A3 start ---");            sleep((long) (Math.random() * 30));        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("--- thread A3 end ---");    }}public class OrderTest {    public static void main(String[] args) {        try {            A1 a1 = new A1();            a1.start();            a1.join();            A2 a2 = new A2();            a2.start();            a2.join();            A3 a3 = new A3();            a3.start();        } catch (InterruptedException e) {            e.printStackTrace();        }    }}// 控制台输入:--- thread A1 start ------ thread A1 end ------ thread A2 start ------ thread A2 end ------ thread A3 start ------ thread A3 end ---

a1.start()使a1进入就绪状态,a1和主线程都可能抢到CPU执行权,a1.join()使 a1 线程独占CPU,主线程要等a1执行完能力执行a2的初始化和a2.start()等后续代码。

另外,把a2的初始化和a2.join()放在a3run()外面的第一行(即执行a3的逻辑代码前),把a1的初始化和a1.join()放在a2run()外面的第一行,也能让a1a2a3程序执行,成果和上述代码雷同。

办法2:wait() & notify()

public class B1 extends Thread{    @Override    public void run() {        synchronized (this){            try {                System.out.println("--- thread B1 start ---");                sleep((long) (Math.random() * 30));                System.out.println("--- thread B1 end ---");                notify();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}public class B2 extends Thread {    @Override    public void run() {        B1 b1 = new B1();        b1.start();        synchronized (b1){            try {                b1.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        synchronized (this){            try {                System.out.println("--- thread B2 start ---");                sleep((long) (Math.random() * 30));                System.out.println("--- thread B2 end ---");                notify();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}public class B3 extends Thread {    @Override    public void run() {        B2 b2 = new B2();        b2.start();        synchronized (b2){            try {                b2.wait();                System.out.println("--- thread B3 start ---");                sleep((long) (Math.random() * 30));            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("--- thread B3 end ---");        }    }}public class OrderTest {    public static void main(String[] args) {        new B3().start();    }}// 控制台输入:--- thread B1 start ------ thread B1 end ------ thread B2 start ------ thread B2 end ------ thread B3 start ------ thread B3 end ---

须要留神的是,线程B2中调用b1.wait()的时候不是让b1对象期待,而是让获取到b1对象同步锁的以后线程期待。这外面的「以后线程」指的就是线程B2了。

线程B1中的notify(),唤醒的是在以后对象上期待的线程(其实这里的notify()相当于this.notiify())。

B2线程的run()外面,执行第一个synchronized代码块的时候,以后线程wait了,当被唤醒的时候继续执行后续代码(即第二个synchronized代码块);B3被唤醒后执行b2.wait()前面的代码:System.out.println("--- thread B3 start ---"); 等。

办法3:线程池

public class OrderTest {    public static void main(String[] args) {        A1 a1 = new A1();        A2 a2 = new A2();        A3 a3 = new A3();        ExecutorService single = Executors.newSingleThreadExecutor();        single.submit(a1);        single.submit(a2);        single.submit(a3);        single.shutdown();    }}// 控制台输入:--- thread A1 start ------ thread A1 end ------ thread A2 start ------ thread A2 end ------ thread A3 start ------ thread A3 end ---
newSingleThreadExecutor只蕴含一个线程,而且能够保障线程按程序执行。

办法4

最容易想到的方法,在一个线程的run()外面的结尾处初始化并启动另一个线程(thread.start()),这个简略就补贴代码了。