咱们在平常的多线程开发中,可能有时会想让每一个线程都按照咱们指定的顺序来运行,而不是让CPU随机调度,这样可能会让咱们在平常的开发工做中带来没必要要的麻烦。既然有了这个需求,也就引入了本文的标题,让线程按照本身指定的顺序来运行。java
有兴趣的同窗能够猜测下列代码可能运行的结果:安全
按照正常的理解思路,上面代码的执行顺序依次应该为:t1 → t2 → t3,而实际效果则不是理想的状态。多线程
下图为运行效果:学习
(1)认识Join
join可能对于一些同窗来讲并不陌生,此处我就不详细介绍Join是什么了,有疑问的同窗能够自行baidu和google。这里我将直接介绍如何使用join来达到咱们但愿看到的效果!google
这里主要是利用Join的阻塞效果,来达到咱们的使用目的。看上图的运行结果能够得知,程序已经按照咱们指定的顺序执行结束了,并获得了咱们想要的结果。spa
其实这里能够深刻的思考一下,为何join能够达到咱们想要的效果呢?接下来咱们来看下源码:线程
进入join源码后,首先看到的是一个传入0参数的join方法,此处选择继续进入。3d
首先能够看到join方法是线程安全的,其次能够结合上图一块儿看,当传入参数为0时,会命中一个wait(0)的方法,有经验的同窗应该能直接看懂,这里表示等待。可是须要说明的是,这里的等待绝对不是等待调用者,而是阻塞的主线程,t1,t2,t3只是子线程,当子线程运行完毕后,主线程结束等待。这里演示了join的工做方式,也证明了join能让咱们在程序中达到本身想要的效果。(即在main主线程中执行t1,t2,t3,若是使用t1.join(),那么表示在主线程中插入了t1线程,此时main主线程阻塞,须要等待t1线程彻底执行完以后,才会继续主线程,即继续main主线程在t1.join()之下的代码)code
除了join能在程序中帮助咱们控制线程的顺序外,还有另外的方式,好比咱们利用线程池实现试一试。blog
(2)利用Executors线程池
Executors是JDK中java.util.concurrent包下线程池操做类,能够方便的为咱们提供线程池的操做。这里咱们使用Executors中的newSingleThreadExecutor()方法,建立一个单线程的线程池。
(3) 利用Thread.sleep()也能够达到一样的效果
try { t1.start(); Thread.sleep(10); t2.start(); Thread.sleep(10); t3.start(); } catch (InterruptedException e1) { e1.printStackTrace(); }
根据上图能够得知,利用newSingleThreadExecutor()方法依然可以达到咱们期待的效果,其实原理很简单,方法内部是一个基于FIFO的队列,也就是说,当咱们依次将t1,t2,t3加入队列中时,实际在就绪状态的只有t1这个线程,t2,t3则会被添加到队列中,当t1执行完毕后,则会继续执行队列中的其余线程。
本章总结:
根据上面的篇幅咱们得知了如何让线程按照指定的方式运行,其实方法还有不少,限于篇幅就不一一列举了,本文只是但愿提供给一些基础很差的同窗以一些思路。本文还有不少细节没有讲解的很清楚,你们能够根据提供的连接深刻的学习。同时但愿你们给予宝贵的意见!