Thread源码剖析(二)

简介: 笔记

1.4线程生命周期


在上一篇介绍的时候其实也提过了线程的线程有3个基本状态:执行、就绪、阻塞

在Java中我们就有了这个图,Thread上很多的方法都是用来切换线程的状态的,这一部分是重点!

33.jpg

其实上面这个图是不够完整的,省略掉了一些东西。后面在讲解的线程状态的时候我会重新画一个~

下面就来讲解与线程生命周期相关的方法~


1.4.1sleep方法


调用sleep方法会进入计时等待状态,等时间到了,进入的是就绪状态而并非是运行状态

34.jpg

于是乎,我们的图就可以补充成这样:

35.jpg


1.4.2yield方法


调用yield方法会先让别的线程执行,但是不确保真正让出

  • 意思是:我有空,可以的话,让你们先执行

36.jpg

于是乎,我们的图就可以补充成这样:

37.jpg

1.4.3join方法


调用join方法,会等待该线程执行完毕后才执行别的线程~

38.jpg

我们进去看看具体的实现

39.jpg

wait方法是在Object上定义的,它是native本地方法,所以就看不了了:

40.png

wait方法实际上它也是计时等待(如果带时间参数)的一种!,于是我们可以补充我们的图:

41.jpg


1.4.3interrupt方法


线程中断在之前的版本有stop方法,但是被设置过时了。现在已经没有强制线程终止的方法了!

由于stop方法可以让一个线程A终止掉另一个线程B

  • 被终止的线程B会立即释放锁,这可能会让对象处于不一致的状态
  • 线程A也不知道线程B什么时候能够被终止掉,万一线程B还处理运行计算阶段,线程A调用stop方法将线程B终止,那就很无辜了~

总而言之,Stop方法太暴力了,不安全,所以被设置过时了。

我们一般使用的是interrupt来请求终止线程~

  • 要注意的是:interrupt不会真正停止一个线程,它仅仅是给这个线程发了一个信号告诉它,它应该要结束了(明白这一点非常重要!)
  • 也就是说:Java设计者实际上是想线程自己来终止,通过上面的信号,就可以判断处理什么业务了。
  • 具体到底中断还是继续运行,应该由被通知的线程自己处理
Thread t1 = new Thread( new Runnable(){
    public void run(){
        // 若未发生中断,就正常执行任务
        while(!Thread.currentThread.isInterrupted()){
            // 正常任务代码……
        }
        // 中断的处理代码……
        doSomething();
    }
} ).start();

再次说明:调用interrupt()并不是要真正终止掉当前线程,仅仅是设置了一个中断标志。这个中断标志可以给我们用来判断什么时候该干什么活!什么时候中断由我们自己来决定,这样就可以安全地终止线程了!

我们来看看源码是怎么讲的吧:

42.jpg

再来看看刚才说抛出的异常是什么东东吧:

43.jpg

所以说:interrupt方法压根是不会对线程的状态造成影响的,它仅仅设置一个标志位罢了

interrupt线程中断还有另外两个方法(检查该线程是否被中断)

  • 静态方法interrupted()-->会清除中断标志位
  • 实例方法isInterrupted()-->不会清除中断标志位

44.jpg45.jpg

上面还提到了,如果阻塞线程调用了interrupt()方法,那么会抛出异常,设置标志位为false,同时该线程会退出阻塞的。我们来测试一波:

public class Main {
    /**
     * @param args
     */
    public static void main(String[] args) {
        Main main = new Main();
        // 创建线程并启动
        Thread t = new Thread(main.runnable);
        System.out.println("This is main ");
        t.start();
        try {
            // 在 main线程睡个3秒钟
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("In main");
            e.printStackTrace();
        }
        // 设置中断
        t.interrupt();
    }
    Runnable runnable = () -> {
        int i = 0;
        try {
            while (i < 1000) {
                // 睡个半秒钟我们再执行
                Thread.sleep(500);
                System.out.println(i++);
            }
        } catch (InterruptedException e) {
            // 判断该阻塞线程是否还在
            System.out.println(Thread.currentThread().isAlive());
            // 判断该线程的中断标志位状态
            System.out.println(Thread.currentThread().isInterrupted());
            System.out.println("In Runnable");
            e.printStackTrace();
        }
    };
}

结果:46.png


接下来我们分析它的执行流程是怎么样的:

47.jpg

目录
相关文章
|
存储 SQL 关系型数据库
PolarDB这个sql行存和列存性能差别好大 ,为什么?
PolarDB这个sql行存和列存性能差别好大 ,为什么?
253 0
|
存储 负载均衡 数据管理
OceanBase分区表优势
【8月更文挑战第13天】OceanBase分区表优势
271 7
|
Python
Python中访问不存在的属性
【6月更文挑战第4天】
299 5
|
Java
解密 Java ForEach 提前终止问题
解密 Java ForEach 提前终止问题
137 0
|
Linux C语言
suse linux 11 安装GCC开发环境
suse linux 11 安装GCC开发环境
268 0
|
JSON 小程序 安全
微信小程序支付
当下,微信小程序十分火爆,现在无论是购物还是生活服务,都是推荐你使用微信小程序,主要是它无需下载安装就可以使用,让手机变得非常清爽,给用户也带来很大的方便之处。
420 2
微信小程序支付
|
XML JSON Android开发
[Android]使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换
[Android]使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换
307 0
|
Oracle Java 关系型数据库
Linux下安装和卸载jdk及环境配置
Linux下安装和卸载jdk及环境配置
496 0
|
关系型数据库 MySQL 数据库
下一篇
开通oss服务