美文网首页程序员每天写500字每天写1000字
如何控制多线程的执行顺序?

如何控制多线程的执行顺序?

作者: 追梦人_奋斗青年 | 来源:发表于2019-03-19 10:36 被阅读0次

我们先来看下面的程序:


线程执行顺序

以上运行程序的结果是什么呢?

有人说结果如下:

main开始运行
thread1运行
thread2运行
thread3运行
main运行结束

有的人说结果如下:

main开始运行
main运行结束
thread1运行
thread3运行
thread2运行

有人说结果如下:

main开始运行
thread2运行
main运行结束
thread1运行
thread3运行

其实啊,这段程序的运行结果可能有很多种。这些不同情况的出现,取决于CPU的调度。

由于存在CPU调度的不确定性,所以多线程的执行顺序具有不确定性。主线程有可能比其他线程先执行完,其他线程也有可能比主线程执行完,其他线程之间执行顺序也可能不同。

那么问题来了,如果想让多线程按我们预期的顺序执行,应该怎么办呢?

比如说,我们希望任何情况下,程序运行的结果如下:

main开始运行
thread1运行
thread2运行
thread3运行
main运行结束

我们该怎么办呢?

下面介绍控制线程执行顺序的2种方法。

方法一:使用join()方法让一个线程强制运行

main方法里关键代码如下:

public static void main(String[] args) {
try {
            System.out.println("main开始运行");
            thread1.start();
            thread1.join(); //让thread1强制执行完毕后,才可以执行后面的代码
            thread2.start();
            thread2.join();
            thread3.start();
            thread3.join();
            System.out.println("main运行结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

使用join()方法后,运行结果则会固定下来,如下:

main开始运行
thread1运行
thread2运行
thread3运行
main运行结束

join()方法原理介绍:

使用join()方法让子线程强制运行,其实是join()方法阻塞了主线程的运行,我们通过join()方法的源码可以看到

public final void join() throws InterruptedException {
        join(0);
    }

调用join方法,会调用join(0)方法,当参数为0时,会调用wait方法,使主线程阻塞,等待子线程执行完毕后,主线程结束等待,继续执行。


join源码

方法二:使用juc包下的Executors线程池保证子线程按顺序执行

Java5.0提供了java.util.concurrent(简称JUC)包,提供了并发编程中一些常用的工具类。

Executors是JDK中java.util.concurrent包下线程池操作类,提供方便的线程池的操作。

我们使用Executors中的newSingleThreadExecutor()方法,创建一个单线程的线程池,也可以达到控制线程执行顺序的目的。

关键代码如下:

static ExecutorService executorService = 
  Executors.newSingleThreadExecutor();
public static void main(String[] args) {
        System.out.println("main开始运行");
        executorService.submit(thread1);
        executorService.submit(thread2);
        executorService.submit(thread3);
        executorService.shutdown();
        System.out.println("main运行结束");
    }

运行结果如下:

main开始运行
main运行结束
thread1运行
thread2运行
thread3运行

从上面的运行结果可以看出,使用newSingleThreadExecutor()方法创建的线程池可以使放到它里面的子线程按一定顺序执行,但是不能保证子线程和主线程的执行顺序。

原理介绍:
newSingleThreadExecutor()方法创建的线程池是一个基于FIFO(先进先出)的队列,也就是说,当我们依次将thread1,thread2,thread3加入队列中时,实际在就绪状态的只有thread1这个线程,thread2,thread3则会被添加到队列中等待,当thread1执行完毕后,则会按进入队列的先后顺序执行队列中的其他线程。

希望大家通过这篇文章了解多线程环境下控制线程执行顺序的2种方法,并能用于实践。

相关文章

  • 如何控制多线程的执行顺序

    方法一:join join方法:让主线程等待子线程运行结束后再继续运行 方法二:Excutors.newSingl...

  • 如何控制多线程的执行顺序?

    我们先来看下面的程序: 以上运行程序的结果是什么呢? 有人说结果如下: main开始运行thread1运行thre...

  • 如何控制多线程执行的顺序?

    先看一段代码: 执行结果: 可以看到线程的执行顺序是随机的。查阅资料控制多线程执行顺序有以下两种方法: 方法1:调...

  • 线程 -- join 功能

    由于多线程的执行是无序的,因此使用 join 对控制多个线程的执行顺序非常关键。 举个例子: def T1_job...

  • unittest测试框架

    一、使用规则 二、重要概念 三、用例执行 1、执行顺序 2、如何控制用例的执行顺序 方法一:通过testSuite...

  • Java基础总结3-多线程

    多线程 1、进程和线程 进程:正在进行的成序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制...

  • python——多线程

    多线程-threading 子类完成创建多线程 线程的执行顺序也是主线程和各个子线程随机执行,顺序不确定 线程对全...

  • 03-unittest中case的执行顺序控制

    1.默认测试方法都是以test开头 ,按照顺序执行 如何控制case按照自定义的顺序执行 或者

  • day11-01/02/03多线程(概述)

    一、多线程 进程:是一个正在执行中的程序每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元线...

  • ABC三个线程如何保证顺序执行

    介绍 最近看看多线程练习题,练习下多线程,这道题:ABC三个线程如何保证顺序执行。三个线程同时启动,然后按照顺序执...

网友评论

    本文标题:如何控制多线程的执行顺序?

    本文链接:https://www.haomeiwen.com/subject/isnwmqtx.html