我们知道在多线程中,线程在启动的时候不是马上去执行任务的,而是由cpu调度让哪一个线程执行,通常情况下多线程的执行顺序是随机的,如果我们想要让线程按照一定的顺序让线程执行,怎么做呢?
1.初见
首先我们先上一段代码,看看执行效果。
1 2 3 4 5 6 7 8 9
| private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行")); private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行")); private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行"));
public static void main(String[] args) { thread1.start(); thread2.start(); thread3.start(); }
|
执行结果如图所示:

从代码运行结果看,线程执行的顺序是随机的,我们无法保证线程按照特定的顺序执行,线程启动之后处于就绪状态,等待CPU调度执行,也就是说如果不做处理话,我们是无法控制的。
2.相恋
2.1 设置线程优先级
线程的执行除了CPU调度外,还有一个因素就是每个线程的优先级,线程的级别有1-10个等级,级别越高表示线程越有可能拿到CPU时间片,但是并不是优先级越高的线程就一定比优先级低的线程更早获得CPU时间片执行任务呢,按但是否定的,我们只能说优先级高的线程更有可能获取的执行权,如果说优先级高的进入了等待,那么优先级低的线程就会执行,如果几个线程都处于就组状态,那毫无疑问优先级高的线程就会先执行。
1 2 3 4 5 6 7 8 9 10 11
| private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行")); private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行")); private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行")); public static void main(String[] args) { thread3.setPriority(Thread.MAX_PRIORITY); thread2.setPriority(Thread.NORM_PRIORITY); thread1.setPriority(Thread.MIN_PRIORITY); thread1.start(); thread2.start(); thread3.start(); }
|

2.2 Thread.join()
我们Thread.join()方法就是让主线程等待,新线程执行完了后再继续执行主线程,让我们来看一下Thread.join()方法的源码吧
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public final void join() throws InterruptedException { join(0); }
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0;
if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); }
if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
|
源码很清晰的告诉我们,当我们调用join()方法后,后调用join(long millis),在millis == 0的情况下,如果当前线程是存活的,就让当前线程等待,让新线程继续执行知道死亡,知道原理后就来实现下代码喔。
1 2 3 4 5 6 7 8 9 10
| private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行")); private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行")); private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行")); public static void main(String[] args) throws InterruptedException { thread1.start(); thread1.join(); thread2.start(); thread2.join(); thread3.start(); }
|

2.3 Executors.newSingleThreadExecutor()
Executors.newSingleThreadExecutor()就是创建一个只有一个线程线程池,让我们看了一个源码吧
1 2 3 4 5 6
| public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
|
我们可以看到Executors.newSingleThreadExecutor()实际上是创建了一个单线程的线程池,并且维护了一个任务队列,我们知道队列的特点就是FIFO(先进先出),而且线程池每次只能执行一个任务线程,其余的线程实际上放到new LinkedBlockingQueue()这个队列里等待CPU调度,当第一个线程执行完了后,线程池就会从队列取下一个任务线程来执行,以此类推,从而保证了线程的执行顺序,来看看代码怎么实现的吧
1 2 3 4 5 6 7 8 9 10
| private static Thread thread1 = new Thread(()->System.out.println("thread1 开始执行")); private static Thread thread2 = new Thread(()->System.out.println("thread2 开始执行")); private static Thread thread3 = new Thread(()->System.out.println("thread3 开始执行")); private static ExecutorService service = Executors.newSingleThreadExecutor(); public static void main(String[] args) throws InterruptedException { service.execute(thread1); service.execute(thread2); service.execute(thread3); service.shutdown(); }
|

婚恋
以上就是控制多线程执行顺序方法,有什么不对欢迎指正喔。