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()方法

相关推荐
摇滚侠39 分钟前
SpringMVC 入门到实战 文件上传 75-77
java·后端·spring·maven·intellij-idea
fox_lht2 小时前
15.3.改进我们之前的输入、输出项目
开发语言·后端·学习·rust
大鸡腿同学3 小时前
用 AI 肝了一个星期的智能客服助手,看看怎么个事
后端
IT_陈寒3 小时前
Python的os.path.join居然能这么坑?
前端·人工智能·后端
张忠琳3 小时前
【Go 1.26.4】Golang Channel 深度解析
开发语言·后端·golang
Rain5093 小时前
2.1 Nest.js 项目初始化与模块化架构
开发语言·前端·javascript·后端·架构·数据分析·node.js
cjp5603 小时前
009. ASP.NET WEB API 用户关联esp32设备
前端·后端·asp.net
贺国亚4 小时前
Text-to-SQL与Analytics-Agent
后端
一只叫煤球的猫4 小时前
ThreadForge 源码解读二:一个 Task 从 submit 到完成,内部到底发生了什么?
java·后端·面试