之前的例子中基本上都用到了线程池,一般我们都是把任务初始化好之后直接丢到线程池就可以了,使用起来非常简单方便。
new Thread弊端
1.每次new Thread都要新建一个对象,性能差。
2.线程缺少统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM。
3.缺少更多功能,如更多执行、定期执行、线程中断。
所以,我们一般不常用Thread,这里就不再细讲了。
线程池好处
1.重用存在的线程,减少对象创建,消亡的开销,性能佳。
2.可有效的控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。
3.提供定时执行、定期执行、单线程、并发数控制等功能。
1.ThreadPoolExecutor
我们来看看ThreadPoolExecutor可以接收的几个参数来做初始化。
(1)corePoolSize:核心线程数量
(2)maximumPoolSize:线程最大线程数
(3)workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响
(4)keepAliveTime:线程没有任务执行时最多保持多久时间终止(当线程池的线程数量大于corePoolSize,如果这时没有新的任务提交,核心线程不会立即销毁,而是让他等待,直到超过这里的keepAliveTime)
(5)unit:keepAliveTime的时间单位
(6)ThreadFactoryL:线程工厂,用来创建线程
(7)rejectHandler:当拒绝处理任务时的策略
如果运行的线程数少于我们的corePoolSize,直接创建新线程来处理任务,即使线程池中的其他线程是空闲的;
如果运行的线程数大于我们的corePoolSize,且小于我们的maximumPoolSize,则只有当workQueue满了的时候,才创建新的线程去处理任务;
如果我们设置的corePoolSize和maximumPoolSize相同的话,那么创建的线程池的大小是固定的,这个时候如果有新任务提交,并且workQueue没满的时候,就把请求放到workQueue里面,等待有空闲的线程来这个队列取出任务;
如果运行的线程数大于maximumPoolSize的时候,这时workQueue也已经满了,那么它就要指定我们后面要讲的指定策略参数来处理。
接下来我们详细介绍一下workQueue队列:
它是保存等待执行的任务的一个阻塞队列,当我们提交一个新的任务到线程池的时候,线程池会根据当前线程池中正在运行着的数量来决定该任务的处理方式,处理方式总共有三种:直接切换,无界队列,有界队列。直接切换就是之前提到的SynchronousQueue,使用的无界队列一般是使用链表队列-LinkedBlockingQueue,如果采用无界队列,线程池中能创建的最大线程数就是corePoolSize。我们这里介绍的workQueue的有界队列,一般是ArrayBlockingQueue,使用这种方式呢我们可以把线程池最大线程数目限制为maximumPoolSize。
详细介绍一下rejectHandler的四种策略:
如果workQueue阻塞队列满了,并且没有空闲的线程池,此时,继续提交任务,需要采取一种策略来处理这个任务。
线程池总共提供了四种策略:
待续...
原文:https://www.cnblogs.com/jmy520/p/12577927.html