前言:
我们在日常的多线程开发中,可能有时会想让每个线程都按照我们指定的顺序来运行,而不是让CPU随机调度,这样可能会让我们在日常的开发工作中带来不必要的麻烦。既然有了这个需求,也就引入了本文的标题,让线程按照自己指定的顺序来运行。
多线程执行顺序
按照正常的理解思路,上面代码的执行顺序依次应该为:t1 → t2 → t3,而实际效果则不是理想的状态。
运行效果:
认识Join
join可能对于一些同学来说并不陌生,此处我就不详细介绍Join是什么了,有疑问的同学可以自行baidu和google。这里我将直接介绍如何使用join来达到我们希望看到的效果!
原理:
这里主要是利用Join的阻塞效果,来达到我们的使用目的。看上图的运行结果可以得知,程序已经按照我们指定的顺序执行结束了,并得到了我们想要的结果。
其实这里可以深入的思考一下,为什么join可以达到我们想要的效果呢?接下来我们来看下源码:
进入join源码后,首先看到的是一个传入0参数的join方法,此处选择继续进入。
首先可以看到join方法是线程安全的,其次可以结合上图一起看,当传入参数为0时,会命中一个wait(0)的方法,有经验的同学应该能直接看懂,这里表示等待。但是需要说明的是,这里的等待绝对不是等待调用者,而是阻塞的主线程,t1,t2,t3只是子线程,当子线程运行完毕后,主线程结束等待。这里演示了join的工作方式,也证实了join能让我们在程序中达到自己想要的效果。
除了join能在程序中帮助我们控制线程的顺序外,还有另外的方式,比如我们利用线程池实现试一试。
利用Executors线程池
Executors是JDK中java.util.concurrent包下线程池操作类,可以方便的为我们提供线程池的操作。这里我们使用Executors中的newSingleThreadExecutor()方法,创建一个单线程的线程池。
原理:
根据上图可以得知,利用newSingleThreadExecutor()方法依然能够达到我们期待的效果,其实原理很简单,方法内部是一个基于FIFO的队列,也就是说,当我们依次将t1,t2,t3加入队列中时,实际在就绪状态的只有t1这个线程,t2,t3则会被添加到队列中,当t1执行完毕后,则会继续执行队列中的其他线程。
总结
根据上面的篇幅我们得知了如何让线程按照指定的方式运行,其实方法还有很多,限于篇幅就不一一列举了,本文只是希望提供给一些基础不好的同学以一些思路。本文还有很多细节没有讲解的很清楚,大家可以根据提供的链接深入的学习。同时希望大家给予宝贵的意见!