学习Thread线程实现原理

1:继承Thread类创建线程

现象:创建线程的第一种方式,继承Thread,重写run方法,如果直接调用run方法,则和调用普通方法一样,不会创建线程

 结果显示是  main线程调用

如果调用start,是 Thread-0 调用

调用run方法,很简单,MyThread类继承Thread,重写了run,所以调用run实际调用的是子类MyThread类的run,

我们来看一下start方法

 大致意思是:

start这个方法触发这个线程开始执行,jvm会调用这个线程的run方法。

导致这两个线程并发执行:当前线程调用完start就就结束了,另一个线程要执行run方法。

启动这个线程超过1次是不合法的,尤其是线程已经执行完成不能再次被重启。

我们通过注释可以看出只有调用start方法才会创建线程,而且是准备就绪,没有执行,具体执行需要

cpu分配时间片给该线程,这个线程只能被启动一次,start方法上面有个synchronized锁,应该就是控制多次启动的。

 多次启动,会报非法状态

 来看一下start方法:

首先是判断线程状态,0为New新建,不是则抛异常,如果是则放入线程组,然后调用

start0方法启动,创建该线程,创建过程设置开关,如果创建失败则从线程组删除

这个start0方法是jvm提供的方法,应该就是为线程开辟内存,分配资源等工作,具体怎么cpu怎么调到run方法的

还不知道,后面研究后 在补充 ?????????

来看一下run方法

 如果这个thread构建的时候以一个runnable对象作为参数,那么启动的时候,将会调用,否则不会被调用,

当然Thread的子类应该重写这个方法

当继承Thread时,已经重写run方法,所以jvm底层调用run时,其实直接调用子类的方法,而不是该方法。

2:实现runnable的方式创建线程

 来看一下构造Thread这个方法

new Thread(runnable);

 

 到最后把入参的target赋值给了内部维护的target变量,

所以当调用start后,创建一个线程就绪状态,等待分配时间片。

再来看一下Thread类的run方法:

 因为没有被重写,所以会调用Thread类的run方法,target就是入参传进来的MyRunnable对象,所以

会调用重写的run方法。

3: 线程池方式创建线程

先来看一下创建线程池对象:

ExecutorService executors = Executors.newSingleThreadExecutor();

 将创建的线程池对象委托给了

FinalizableDelegatedExecutorService 对象,

 在这个

DelegatedExecutorService类里面,将入参委托给了ExecutorService来维护。

在回过头来看线程池的execute方法:

然后调用到ThreadPoolExecutor方法

由于线程池里面的参数比较多,我们就假设线程池工作的线程数小于核心数:

先重点关注一下线程池的执行逻辑,具体线程池的细节可以在线程池一节在重点分析:

 

看一下new Worker(firstTask) 方法:

将runnable赋值给worker类中的变量,然后使用线程工厂创建一个线程,同时将当前worker对象作为参数传进了线程中。

因为Worker类也实现了Runnable接口

 

由于我们创建线程时使用的是默认线程工厂:

 所以看一下newThread的逻辑

 将worker作为入参传了进去,然后维护在Thread类中的target变量上。

当把worker对象放到集合workers中,添加成功后,会调用线程的start方法。

调用start方法,当cpu分配时间片给Thread时,就触发了Worker对象的run方法

调用runWorker方法,就会调用MyRunnable方法的run方法,

就会调用我们自己实现的MyRunnable方法中。

原文地址:https://www.cnblogs.com/warrior4236/p/12434109.html