Thread简单的源码阅读

开启线程后主线程会阻塞嘛?

csharp 复制代码
public class Thread01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();
​
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                System.out.println("当前线程继续执行" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
​
    }
}
​
class Cat extends Thread {
    @Override
    public void run() {
        int count = 0;
        while (true) {
​
            try {
                System.out.println("喵喵叫、、、、、、、、" + (++count) + Thread.currentThread().getName());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 30) {
                break;
            }
        }
​
    }
}

代码运行结果

可以看出主线程里面,如果开启了一个其他线程,主线程并不会阻塞。由于CPU的来回切换,一会执行main线程代码一会执行其他线程的代码。

初始化原理

csharp 复制代码
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}
​
  • 默认情况下,如果不指定线程的名称,那么自动生成的线程名称就是,Thread-0,Thread-1,以此类推的一大堆的线程。
  • 进入到init()方法之后 如下图所示:

说明: 创建线程的时候,获取到的是currentThread(),是当前创建的那个线程,比如说一般来说就是那个main线程,main线程在创建XXXX线程,所以说此时创建线程的过程中,获取到的currentThread()就是main线程

创建一个线程的时候,默认他的父线程就是创建他的那个线程,比如main线程创建XXXX线程,此时XXXX线程的父线程就是main线程。

  • 分配线程组

    scss 复制代码
    if (g == null) {
        /* Determine if it's an applet or not */
    ​
        /* If there is a security manager, ask the security manager
           what to do. */
        if (security != null) {
            g = security.getThreadGroup();
        }
    ​
        /* If the security doesn't have a strong opinion of the matter
           use the parent thread group. */
        if (g == null) {
            g = parent.getThreadGroup();
        }
    }

上面这段代码的意思,就是说threadGroup是不指定的,他就会自动给你处理一下,给你分配一个线程组,每个线程必须属于一个ThreadGroup的。如果你没有指定线程组,那么你默认的线程组就是父线程的线程组。

如果你的父线程是main线程的话,那么你的线程组就是main线程的线程组(main线程组)。默认情况下,如果你没有指定你是否为daemon的话,那么你的daemon的状态是由父线程决定的,就是说如果你的父线程是daemon线程,那么你也是daemon线程;同理,你的优先级如果没有指定的话,那么就跟父线程的优先级保持一致

在 Java 中,有两种类型的线程:用户线程和守护线程(Daemon 线程)。用户线程是指主线程和其他由主线程创建的线程,它们的工作通常是完成一些具体的任务或者实现某些功能。而守护线程是指在后台运行的线程,它们通常用于提供服务和支持其他线程的运行。

守护线程与用户线程的最大区别是,当 JVM 中只有守护线程时,JVM 将会退出。守护线程不会阻止 JVM 的退出,当 JVM 中只有守护线程时,JVM 将会自动退出,而不考虑这些线程是否执行完毕。

ini 复制代码
tid = nextThreadID();

每个线程其实都有一个线程id,threadId,第一个分配的线程,它的id是1,之后的线程是2,3,4,5,这样子,依次分配各个线程的id

总结:

(1)创建你的线程,就是你的父线程

(2)如果没有指定ThreadGroup,ThreadGroup就是父线程的ThreadGroup

(3)daemon状态默认是父线程的daemon状态

(4)你的优先级默认是父线程的优先级

(5)如果你没有指定线程的名称,那么默认就是Thread-0格式的名称

(6)你的线程id是全局递增的,从1开始

对一个线程进行start的时候的原理

scss 复制代码
if (threadStatus != 0)
throw new IllegalThreadStateException();

说明永远都不能对一个线程多次调用和执行start()方法,这个是不对的。

如果线程一旦执行过一次以后,那么他的threadStatus就一定会变为非0的一个状态,如果threadStatus是非0的状态,说明他之前已经被执行过了,所以这里会有一个判断,如果对一个线程多次执行start()方法,会抛出一个异常,IllegalThreadStateException,非法的线程状态的异常。

csharp 复制代码
group.add(this);

group就是之前给分配的,如果你自己指定了,那么就是你自己创建的那个ThreadGroup,否则的话就是你的父线程的threadGroup,这行代码,其实就是将当前线程加入了他属于的那个线程组。

csharp 复制代码
private native void start0();

会结合底层的一些代码和机制,实际的启动一个线程。一旦是start0()成功的启动之后,他就会去执行我们覆盖掉的那个run()方法,或者是如果你传入进去的是那个Runnalbe对象,他就会执行那个Runnable对象的方法

csharp 复制代码
public void run() {
        if (target != null) {
            target.run();
        }
}
csharp 复制代码
new Thread(new Runnable() {

public void run() {
}

}).start();

如果传递进去了一个Runnable对象,就是在thread类里是target的东西,会判断一下,如果target为null的话,那么此时就会执行target的run方法。反之,如果你是直接自己用Thread类继承了一个子类的话,那么你会重写这个run()方法,start0()启动线程之后,就会来执行你的run()方法

总结:

(1)一旦启动了线程之后,就不能再重新启动了,多次调用start()方法,因为启动之后,threadStatus就是非0的状态了,此时就不能重新调用了

(2)你启动线程之后,这个线程就会加入之前处理好的那个线程组中

(3)启动一个线程实际上走的是native方法,start0(),会实际的启动一个线程

(4)一个线程启动之后就会执行run()方法

相关推荐
小咕聊编程6 分钟前
【含文档+源码】基于SpringBoot的过滤协同算法之网上服装商城设计与实现
java·spring boot·后端
追逐时光者6 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_6 小时前
敏捷开发流程-精简版
前端·后端
苏打水com7 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧8 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧8 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧8 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧8 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧8 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng10 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端