多线程顺序执行,只知道两种?

故事

上周一位同学在面试中遇到了这么一道问题:

有三个线程T1、T2、T3,如何保证顺序执行?

常规操作,启动三个线程,让其执行。

public class ThreadDemo { public static void main(String[] args) { final Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("线程1"); } }); final Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("线程2"); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { System.out.println("线程3"); } }); t1.start(); t2.start(); t3.start(); } }登录后复制

线程2 线程1 线程3登录后复制

怎么办呢?下面我们使用四种方案来实现。

方案一

我们可以利用Thread中的join方法解决线程顺序问题,下面我们来简单介绍一下join方法。

官方介绍:

Waits for this thread to die.

等待这个线程结束,也就是说当前线程等待这个线程结束后再继续执行 。

join()方法是Thread中的一个public方法,它有几个重载版本:

  • join()
  • join(long millis) //参数为毫秒
  • join(long millis,int nanoseconds) //第一参数为毫秒,第二个参数为纳秒

join()方法实际是利用了wait()方法(wait方法是Object中的),只不过它不用等待notify()/notifyAll(),且不受其影响。

它结束的条件是:

  • 等待时间到
  • 目标线程已经run完(通过isAlive()方法来判断)

下面大致看看器源码:

public final void join() throws InterruptedException { //调用了另外一个有参数的join方法 join(0); } public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis t2.start()) .thenRun(()->t3.start()); } static class Work implements Runnable{ @Override public void run() { System.out.println("执行 : " + Thread.currentThread().getName()); } } }登录后复制

执行 : 线程1 执行 : 线程2 执行 : 线程3登录后复制

总结

关于多个线程顺序执行,不管是对于面试,还是工作,关于多线程顺序执行的解决方案都是非常有必要掌握的。也希望下次面试官再问:多线程顺序执行问题的时候,你的表情应该是这样的:

多线程顺序执行,只知道两种?