Thread原理

77 阅读4分钟

初始化原理

init(null, null, "Thread-" + nextThreadNum(), 0);

默认情况下,如果你不指定线程的名称,那么自动生成的线程名称就是,Thread-0,Thread-1,以此类推的一大堆的线程。

Thread parent = currentThread();

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

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

f (g == null) {
            if (security != null) {
                g = security.getThreadGroup();
            }
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

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

如果你的父线程是main线程的话,那么你的线程组就是main线程的线程组(main线程组)

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

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的时候的原理

if (threadStatus != 0)
throw new IllegalThreadStateException();

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

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

group.add(this);

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

private native void start0();

会结合底层的一些代码和机制,实际的启动一个线程

一旦是start0()成功的启动之后,他就会去执行我们覆盖掉的那个run()方法,或者是如果你传入进去的是那个Runnalbe对象,人家就会执行那个Runnable对象的方法

public void run() {
        if (target != null) {
            target.run();
        }
}

如果你是

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