java线程池ThreadPoolExecutor

1 submit的Runnable为什么通过Future获取任务的执行结果

submit的Runnable被封装成了FutureTask对象,并且返回。

Runnable执行的结果是在哪里交给FutureTask的?

FutureTask重写了Runnable的run()方法,在这个run()方法中,将任务的返回值放在了FutureTask的outcome成员中。

这样在主线程中就可以获取到该任务的执行结果了。

如果想要获取任务真正的执行结果得传入一个Callable类型的任务,而不能是Runnable类型的任务。如果传入Runnable类型的任务,就算给了一个返回值,也不是Runnable任务的返回值,而就是这个指定的返回值。

2 beforeExecute和afterExecute有什么用

beforeExecute是在任务执行之前执行的,afterExecute是在任务执行之后执行的,可以在里面添加日志、监控、统计信息。比如统计各个线程的执行时间等。

3 线程池的任务队列

 线程池的任务队列就是一个BlockingQueue,可以是ArrayBlockingQueue,这个时候任务队列是固定大小的,如果任务过多的话,就会出现处理不了的情况。

线程池的任务队列的数据是自己设置的。

4 线程池的线程数目

4.1 corePoolSize 

向线程池添加新的任务的时候,如果线程数小于corePoolSize的时候,就会为该任务新创建一个线程。

如果allowCoreThreadTimeOut没有设置的话,该线程池至多有corePoolSize这么多的线程可以一直idle状态而不退出。

4.2 maximumPoolSize

maximumPoolSize是线程池中允许的最大线程数。

4.3 keepAliveTime

如果设置了allowCoreThreadTimeOut的话,所有的线程在没有任务的时候最多的生存时间,如果超过了keepAliveTime的话,就会被销毁。

如果没有设置allowCoreThreadTimeOut的话,核心线程是不受该值影响的。超过了corePoolSize的线程会有一个keepAliveTime的生存时间,超过了该时间没有新的任务的话,该线程会被销毁。

5 works集合和workQueue

works集合是线程池中的线程集合;workQueue是被挂起的任务集合。 

5.1 workQueue的大小

如果是ArrayBlockingQueue,在创建线程池的时候,需要指定这个值。

5.2 works集合的大小

corePoolSize和maximumPoolSize配置的。

6  workQueue中等待的任务是如何被works消费掉的

 每个worker的run()方法本质上是调用了runWorker函数,在这个函数中有一个while循环,不断的去workQueue中获取新的任务执行。如果workQueue中没有新的任务了,有两个情况,如果配置为不timeout的话,核心线程会在阻塞队列上睡眠,等待新的任务的到来;如果配置了timeout的话,核心线程会退出,以后有新的任务的时候再创建。

当ThreadPoolExecutor调用execute加入新的任务的时候,如果works不够corePoolSize的话又回新建新的线程到线程池。

也就是说,ThreadPoolExecutor的execute是生成者,不断加入新的任务,而每个work即每个线程的runWorker是消费者,不断的从workQueue中获取新的任务。

 

7 corePoolSize、maximumPoolSize和workQueue的关系

新加一个任务的时候,如果线程池中的线程数小于corePoolSize的话,直接添加新的线程,如果大于等于corePoolSize,先试图将新的任务放入workQueue中,如果放不下的话,就新建一个线程,但是总的线程数不能超过maximumPoolSize。如果线程数已经超过了maximumPoolSize,那么reject处理这个任务,将这个任务交给RejectedExecutionHandler去处理。

核心线程是最基本的worker,如果处理不过来就将任务放入任务队列中,这是第一道防止任务丢失的屏障。但是核心线程处理任务队列中的任务有一定的速度,加入任务来得太快的话,它就应付不过来了,会导致任务队列满了,再也放不下新的任务了,这个时候,就说明核心线程的处理能力不够,就会添加新的线程来帮助核心线程,这是第二道屏障。但是如果还是处理不过来的话,就只能够丢掉了。这个任务就交给RejectedExecutionHandler去处理。

比如ThreadPoolExecutor的DiscardOldestPolicy这个策略,它把workQueue中最老的任务丢掉,然后把这个最新的任务投入执行。

 

20 参考资料

20.1 https://juejin.im/entry/58fada5d570c350058d3aaad

20.2 https://www.cnblogs.com/dolphin0520/p/3932921.html

 

posted @ 2019-05-24 10:27  PhoenixTree(梧桐树)  阅读(267)  评论(0编辑  收藏  举报