Java线程池详解_JDK1.8.0_191

匿名 (未验证) 提交于 2019-12-02 21:52:03

Java线程池


线程池的作用

1.重用存在的线程,减少处理多请求时线程创建、销毁产生的开销。

2.请求达到时工作线程通常已经存在,请求无需等待,提高系统的响应性。


Executors中线程池的静态工厂方法

1.newFixedThreadPool

创建一个定长的线程池,每当提交一个任务就创建一个线程,直到达到池的最大长度,这时线程池会保持长度不再变化。

2.newCachedThreadPool

创建一个可缓存的线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活地回收空闲的线程,当需求增加时,它可以灵活添加新的线程。

3.newSingleThreadExecutor

创建一个单线程化的executor,它只创建唯一的工作者线程来执行任务,executor会保证任务依照任务队列所规定的顺序(FIFO、LIFO、优先级)执行。

4.newScheduledThreadPool

创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。


ThreadPoolExecutor类中线程池的构造函数

/**  * 通过给定的初始化参数创建一个线程池(ThreadPoolExecutor)  *  * @param corePoolSize 线程池的核心线程数,核心线程即使空闲也不会被销毁, *        除非allowCoreThreadTimeOut被设置  * @param maximumPoolSize 线程池中允许的最大线程数  * @param keepAliveTime 表示当前线程数大于核心线程数时,空闲线程被销毁前 *        等待新任务到达的最大时间  * @param unit keepAliveTime参数的时间单位  * @param workQueue 在任务被执行前用来存放的队列,这个队列将仅仅存放execute方法提交的Runnable任务  * @param threadFactory executor创建新线程所用的工厂  * @param handler 由于线程数量和队列容量已满,执行被阻塞时的拒绝策略  * @throws IllegalArgumentException if one of the following holds:<br>  *         {@code corePoolSize < 0}<br>  *         {@code keepAliveTime < 0}<br>  *         {@code maximumPoolSize <= 0}<br>  *         {@code maximumPoolSize < corePoolSize}  * @throws NullPointerException if {@code workQueue}  *         or {@code threadFactory} or {@code handler} is null  */ public ThreadPoolExecutor(int corePoolSize,                           int maximumPoolSize,                           long keepAliveTime,                           TimeUnit unit,                           BlockingQueue<Runnable> workQueue,                           ThreadFactory threadFactory,                           RejectedExecutionHandler handler) {     if (corePoolSize < 0 ||         maximumPoolSize <= 0 ||         maximumPoolSize < corePoolSize ||         keepAliveTime < 0)         throw new IllegalArgumentException();     if (workQueue == null || threadFactory == null || handler == null)         throw new NullPointerException();     this.acc = System.getSecurityManager() == null ?             null :             AccessController.getContext();     this.corePoolSize = corePoolSize;     this.maximumPoolSize = maximumPoolSize;     this.workQueue = workQueue;     this.keepAliveTime = unit.toNanos(keepAliveTime);     this.threadFactory = threadFactory;     this.handler = handler; }

1.核心线程数:即使在空闲时也不会被销毁的线程数

2.最大线程数:线程池中允许的最大线程数

3.保持存活时间:空闲线程在被销毁之前等待新任务的时间

4.存活时间单位:等待时间的单位

5.工作队列:存放待执行任务的队列

6.线程工厂:新线程创建的工厂

7.拒绝策略:当线程数量和队列已满时采取的拒绝策略


工作队列

工作队列有多种,但都实现BlockQueue接口

队列类型 线程池类型 特点
LinkedBlockingQueue

FixedThreadPool

SingleThreadPool

使用的工作队列

基于链表的先进先出队列
SynchronousQueue CachedThreadPool使用的工作队列 不保存提交的任务,而是直接创建一个线程来执行新任务
DelayedWorkQueue ScheduledThreadPool使用的工作队列

拒绝策略

1.AbortPolicy:直接丢弃任务并抛出RejectedExecutionException异常。

2.CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。

3.DiscardOldestPolicy:丢弃队列中最老的一个任务,也就是即将要执行的任务,并再次尝试提交当前任务。

4.DiscardPolicy:丢弃任务,不做任何处理。


线程池的任务处理如下图所示

逻辑较为清晰,其实这是线程池execute()方法的逻辑,下面看一下源码:

//通过execute向线程池提交任务public void execute(Runnable command) {     if (command == null)         throw new NullPointerException();     int c = ctl.get();    //如果当前线程数未达到核心线程数,则直接创建线程来执行新任务     if (workerCountOf(c) < corePoolSize) {         if (addWorker(command, true))             return;         c = ctl.get();     }    //否则将任务加入阻塞队列,这里进行双重检查,如果线程池已经关闭,则调用reject(),    //如果当前线程池线程数为0,则新建线程     if (isRunning(c) && workQueue.offer(command)) {         int recheck = ctl.get();         if (! isRunning(recheck) && remove(command))             reject(command);         else if (workerCountOf(recheck) == 0)             addWorker(null, false);     }    //如果加入阻塞队列失败,则尝试新建一个线程,如果失败了    //则说明线程池关闭了或者线程达到最大线程数,因此调用reject()     else if (!addWorker(command, false))         reject(command); }

线程池提供了两个方法,用来关闭线程池。

(1)shutdown():不会立即关闭线程池,但也不接受新的任务,等待队列中所有任务执行完毕后关闭。

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


线程池的线程数应该如何设置

IO密集型:w/c>1,因此线程数应该为cpu的数倍,但需要考虑线程所占内存,因此通常将线程数设置为cpu的2倍。

CPU密集型:w/c=0,因此线程数为CPU个数。通常将线程数设置为CPU+1,防止线程由于偶尔出现的原因而暂停。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!