深入理解线程池

来源:互联网 发布:何谓文化余秋雨知乎 编辑:程序博客网 时间:2024/05/16 03:35

1.为什么创建线程池

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

线程池中的线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务。

2.最核心的ThreadPoolExecutor

该类位于java.util.concurrent包下。该类继承了抽象类AbstractExecutorService,而AbstractExecutorService实现了ExecutorService接口,ExecutorService又是继承了Executor接口。Executor接口的实现:

public interface Executor{

void execute(Runnable command);

}

该方法就是用来执行传进去的任务。

该类有4种构造器,构造器中有以下参数:

corePoolSize:核心池大小。若线程池中的线程数目达到这个值后,就会把达到的任务放到缓存队列当中;

maximumPoolSize:线程池最大线程数,表示在线程池中最多能创建多少个线程。

keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不大于corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,知道线程池中的线程数为0;

unit:参数keepAliveTime的时间单位,有7种取值。

workQueue:一个阻塞队列,用来存储等待执行的任务。一般来说,有ArrayBlockingQueue(使用较少,创建时必须指定大小)和LinkedBlockingQueue(如果没指定大小,则默认Interger.MAX_VALUE)、SynchronousQueue(它不会保存提交的任务,而是将直接新建的一个线程来执行新来的任务)。

threadFactory:线程工厂,主要用来创建线程;

handler:表示当拒绝处理任务时的策略。


补充:如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;

如果当前线程池中的线程数目≥corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;

如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;

如果线程池中的线程数目>corePoolSize,如果某线程空闲时间超过keepAliveTime,线程将终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

3.线程池中的线程初始化

默认情况下,创建线程池之后,线程池中是没有线程的,需要提交任务之后才会创建线程。

在实际中如果需要线程池创建之后立即创建线程,可以通过以下两个方法办到:

prestartCoreThread():初始化一个核心线程;

prestartAllCoreThreads():初始化所有核心线程。

4.线程池的关闭

shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。

shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

5.线程池容量的动态调整

setCorePoolSize():设置核心池大小

setMaximumPoolSize:设置线程池最大能创建的线程数目大小。

6.Executors类

不提倡直接使用ThreadPoolExecutor,而是使用Executors类提供的几个静态方法来创建线程池:

Executors.newCachedThreadPool();将corePoolSize设置为0,将maximumPoolSize设置为Interger.MAX_VALUE,使用SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。

Executors.newFixedThreadPool():创建的corePoolSize和maximumPoolSize值是相等的,

它使用LinkedBlockingQueue;

Executors.newSingleThreadPool():将corePoolSize和maximumPoolSize值都设置为1

也使用LinkedBlockingQueue。

7.如何合理配置线程池的大小

一般需要根据任务的类型来配置线程池大小:

如果是cpu密集型任务,就需要尽量压榨cpu,参考值可设为Ncpu+1;

如果是IO密集型任务,参考值可以设置为2*Ncpu。

当然,这只是参考值,具体还要根据实际情况进行调整,观察任务运行情况和系统负载、资源

利用率来进行适当调整。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 麦芒6针丢了怎么办 麦芒6扬声器坏了怎么办 华为手机2s太卡怎么办 华为麦芒6网速慢怎么办 华为麦芒5太卡怎么办 小米note3拍照反应慢怎么办 华为刷机后还要账号密码怎么办 刷机后忘记华为账号和密码怎么办 荣耀7x耗电快怎么办 小米2s死机后怎么办? 电信合约卡不想用了怎么办 vivo合约机掉了怎么办 华为合约机丢了怎么办 两年合约机掉了怎么办 电信合约机丢了怎么办 s8合约机坏了怎么办 合约机的卡掉了怎么办 移动合约机屏幕碎了怎么办 5s用不了电信卡怎么办 vivo手机4g信号差怎么办 电信dns辅服务器未响应怎么办 笔记本wifi下载速度慢怎么办 苹果wifi下载速度慢怎么办 小米手机wifi下载速度慢怎么办 苹果8plus上网慢怎么办 小米5c死机了怎么办 苹果x自拍反方向怎么办 硅胶手机壳出油怎么办 指环扣松了怎么办图解 塑料放久了发粘怎么办 橡胶时间久了粘怎么办 胶的手机套变黄怎么办 手机壳硅胶变黄怎么办 硅胶手机壳大了怎么办 硅胶手机壳变大了怎么办 硅胶手机壳有点大怎么办 硅胶手机壳粘手怎么办 透明手机壳变黄怎么办? 耳机胶套经常掉怎么办 硅胶手机壳粘毛怎么办 耳机海绵套坏了怎么办