博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
理解线程池中线程的复用原理
阅读量:5287 次
发布时间:2019-06-14

本文共 3555 字,大约阅读时间需要 11 分钟。

线程的运行是一种非常黑盒的设计,我们只知道调用start(start0;)就完事了,start0是native方法,啥时候调用run方法?反正jvm会帮我们执行run方法,执行完run方法这个线程自动消亡。

 

我们的的run方法是再普通不过的普通方法,看不到jvm在start0之后的代码运行情况

 

线程有两种实现方式,一种是继承Thread,重写run方法,一种是自己写一个Task实现runable接口重写run方法,他们的启动方式 分别是如下

//第一种方式,继承Thread,重写run方法后的启动new MyThread().start();//第二种方式,将实现的runable接口的task作为参数传入Thread构造方法new Thread(new Runnable() {    @Override    public void run(){        System.out.println("do something");    }}).start();
 

jvm执行完run方法,就会执行退出方法,该退出方法在jvm内部用C++语言写的

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {  //线程退出的方法}
 

我们看这两种线程启动方式,感觉启动一次只能传一个任务进去。而且run方法又是由黑盒的jvm执行的,jvm执行完run方法就退出了,那线程池是怎么传多个任务进去的?怎么控制run方法一直执行的?

 

这一系列疑问,要进入线程池源码才能略知一二

 

源码实在太复杂了,我们从前文的铺垫开始,以正常人的思路,首先找到我们的主角---线程

1,线程池中的线程在哪?

当我们没有将线程工厂传入的时候使用的是默认的线程工厂

//1,ThreadPoolExecutor的构造方法众多,但都指向一个,那就是如下this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,             Executors.defaultThreadFactory(), handler);​//2,将Executors.defaultThreadFactory()进入会发现默认线程工厂public static ThreadFactory defaultThreadFactory() {        return new DefaultThreadFactory();}//3,在哪触发产生线程?在如下构造方法里,//产生线程的s时候将这个内部类this本身传递进去Worker(Runnable firstTask) {    setState(-1); // inhibit interrupts until runWorker    this.firstTask = firstTask;    this.thread = getThreadFactory().newThread(this);}//4,进入产生线程的方法public Thread newThread(Runnable r) {    Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);    ...//其他代码    return t;}

 

 

好了我们的线程主角已经登场,但是他的登场并没有多高大上,而是寄人篱下在一个名叫Worker的内部类里

 

这个意思是只要 new Worker(Runnable firstTask),就会产生一个线程,并且产生线程的时候将这个内部类本身this传入进去当task。

 

这似乎跟我们前文讲的差不多,new一个线程就放一个task,说好的线程复用呢?好了主角线程有了,我们的task也有了,我们再找找start方法

//线程启动的时候private boolean addWorker(Runnable firstTask, boolean core) {  w = new Worker(firstTask);  final Thread t = w.thread;  ...//代码  t.start();  ...//代码}
 

线程是启动了,别忘了,线程启动的时候我们将内部类worker对象传入进去了,内部类Worker是实现了runable接口的,jvm执行run方法的时候就会执行Worker中的run方法

//1,这是Work中的一个方法,线程启动的时候jvm会执行它,public void run() {  runWorker(this);}​//2,继续看里面的runWorker(this);很显然this是内部类Work对象本身final void runWorker(Worker w) {        Thread wt = Thread.currentThread();        Runnable task = w.firstTask;        w.firstTask = null;        ../代码        try {            while (task != null || (task = getTask()) != null) {            try{                ../代码                task.run();                }catch(){                ../代码                } finally {                    ../代码                }            }            ../代码        } finally {            ../代码        } }
 

很显然这个runWorker很不得了,里面一个大大的while循环,当我们的task不为空的时候它就永远在循环,并且会源源不断的从getTask()获取新的任务,继续看getTask()方法

 

//很显然这个方法是从队列中获取任务workQueueprivate Runnable getTask() {       ...//代码       // Are workers subject to culling?        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;        if ((wc > maximumPoolSize || (timed && timedOut))            && (wc > 1 || workQueue.isEmpty())) {            if (compareAndDecrementWorkerCount(c))                return null;            continue;        }                try {            Runnable r = timed ?                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :                workQueue.take();            if (r != null)                return r;            timedOut = true;        } catch (InterruptedException retry) {            timedOut = false;        }    }}
 

很显然,getTask()方法里面有个三元表达式,当条件为真时从任务对列workQueue.take()里面获取要执行得任务;

 

讲到这里线程复用的流程就讲完了,最核心的一点是,新建一个Worker内部类就会建一个线程,并且会把这个内部类本身传进去当作任务去执行,这个内部类的run方法里实现了一个while循环,当任务队列没有任务时结束这个循环,则这个线程就结束。

 

 

 

转载于:https://www.cnblogs.com/qq289736032/p/11159951.html

你可能感兴趣的文章
SCIP 练习集
查看>>
在.NET Core控制台应用程序中使用强类型配置
查看>>
Matlab JPEG详细介绍
查看>>
NPOI导入excel
查看>>
Yarn资源调度管理
查看>>
JSON数据解析
查看>>
渗透资源大全
查看>>
jQuery简介
查看>>
作业3
查看>>
如鹏网 静态Web开发 第五章:JQuery
查看>>
sublime 常用快捷键
查看>>
xgb+lr
查看>>
[POST] What Is the Linux fstab File, and How Does It Work?
查看>>
spark 熟悉过程
查看>>
oracle NVL与Coalesce的区别
查看>>
03-11考试总结
查看>>
Linux yum安装过程图文详解
查看>>
bzoj2733: [HNOI2012]永无乡
查看>>
一文读懂MapReduce
查看>>
30个新鲜的社会化图标集合
查看>>