初始化原理
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()方法