多线程运行条件下,Thread如何实现线程按顺序运行?

原理概述

我们知道,在java多线程运行时,通常线程的运行的先后是“随机”的——由jvm根据运行时环境调度执行的。

也就是说,这多个线程程序的执行顺序是不一定的,它的执行顺序还跟线程分的时间片有关。

  CPU运算的时间 是分时间片 分给不同的线程的 一个线程执行完 或者用完了当前它分到的那个时间片 他就得让出CPU给其他线程使用啦!

  线程化是允许多个活动共存于一个进程中的工具。大多数现代的操作系统都支持线程,而且线程的概念以各种形式已存在了好多年。Java 是第一个在语言本身中显式地包含线程的主流编程语言,它没有把线程化看作是底层操作系统的工具。

  有时候,线程也称作轻量级进程。就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。

  进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。

  Java 线程工具和 API 看似简单。但是,编写有效使用线程的复杂程序并不十分容易。因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰。

  每个 Java 程序都使用线程,  每个 Java 程序都至少有一个线程 ― 主线程。当一个 Java 程序启动时,JVM 会创建主线程,并在该线程中调用程序的 main() 方法。

那如何实现多个线程的顺序执行呢?

其实,可以通过Thread的join方法实现。

顺序执行线程

先看个小例子,目标是让线程按照T3,T2,T1的顺序执行。

多线程运行条件下,Thread如何实现线程按顺序运行?

多线程运行条件下,Thread如何实现线程按顺序运行?

public class T3 implements Runnable {private String threadName;public T3(String name){this.threadName = name;}public void run() {System.out.println("T3 is running:"+threadName);}}

调用执行线程:

public class MySequenceThread {

public static void main(String[] args) {

new Thread(new T1("Thread-T1")).start();

}

}

输出结果:T1调用T2的join后,T2子线程正常运行,T2调用T3的join后,T3子线程正常运行,T2等待T3运行结束后再运行,T1等待T2运行结束后再运行。运行结果如下图:

多线程运行条件下,Thread如何实现线程按顺序运行?

这里关键的的就是join函数了,join作用:让主线程等待子线程执行完成后再执行,

源码分析如下:

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;}}}
public final synchronized void join(long millis, int nanos)throws InterruptedException {if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++;}join(millis);}
public final native boolean isAlive();

最终实际调用的是 public final synchronized void join(long millis) throws InterruptedException 方法,下面看下这个方法:以mils参数为0来解释

主线程A中调用子线程B的join()方法,同时获取到了子线程B实例的锁(其他线程可以进入子线程B的join()方法,但是无法进入子线程B的join(0)方法),join(0)方法一直在调用native方法isAlive()检测子线程B的状态,如果子线程B是active的状态,调用子线程B的wait方法,此时主线程A释放了锁(wait方法会释放锁),其他线程可以竞争子线程B的实例锁。如果检测到子线程B的状态不是active,主线程A继续运行。


多线程运行条件下,Thread如何实现线程按顺序运行?


分享到:


相關文章: