Java面向对象系列面向对象系列[v1.0.0][线程池线程池]
系统启动一个新的线程需要与操作系统进行交互,往往消耗的成本比较高,在某些情况下,使用线程池可以很好的提升性能,尤其当成中需要
创建大量生存期很短的的线程时,更应该考虑使用线程池
线程池在系统启动时就创建大量的空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个空闲的线程来执行
他们的run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个
Runnable对象的run()或call()方法
此外,线程池还可以有效的控制并发线程的数量,它的最大线程数参数可以控制系统中并发线程数不超过此数
Java5之前必须手动实现自己的线程池,从Java5开始Java内建支持线程池,Java5新增了一个Executors工厂类来产生线程池,该工厂类包含
如下几个静态工厂方法来创建线程池
newCachedThreadPool(): 创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中,该方法返回一个
ExecutorService对象,该对象代表一个线程池,他可以执行Runnable对象或Callable对象所代表的线程
newFixedThreadPool(int nThreads): 创建一个可重用的、具有固定线程数的线程池,该方法返回一个ExecutorService对象,该对象代表一个
线程池,他可以执行Runnable对象或Callable对象所代表的线程
newSingleThreadExecutor(): 创建一个只有单线程的线程池,它相当于调用newFixedThreadPool()方法时传入参数为1,该方法返回一个
ExecutorService对象,该对象代表一个线程池,他可以执行Runnable对象或Callable对象所代表的线程
newScheduledThreadPool(int corePoolSize): 创建只有指定线程数的线程池,它可以在指定延迟后执行线程任务,corePoolSize指池中所保存
的线程数,即使线程是空闲的也被保存在线程池内,该方法返回一个ScheduledExecutorService线程池,它是ExecutorService的子类,它可以
在指定延迟后执行线程任务
newSingleThreadScheduledExecutor(): 创建只有一个线程的线程池,它可以在指定延迟后执行线程任务,该方法返回一个
ScheduledExecutorService线程池,它是ExecutorService的子类,它可以在指定延迟后执行线程任务
ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来竞
争,Java8新增的该方法可充分利用多CPU并行的能力,它生成的work stealing池相当于后台线程池,如果所有的前台线程都死亡了,work
stealing池中的线程会自动死亡
ExecutorService newWorkStealingPool(): 该方法是前一个方法的简化版,如果当前机器有4个CPU,则目标并行级别被设置为4,也就是相当
于为前一个方法传入4作为参数,Java8新增的该方法可充分利用多CPU并行的能力,它生成的work stealing池相当于后台线程池,如果所有
的前台线程都死亡了,work stealing池中的线程会自动死亡
ExecutorService代表尽快执行线程的线程池,意思就是只要线程池中有空闲线程,就立即执行线程任务,程序只要将一个Runnable对象或
Callable对象(线程任务)提交给该线程池,该线程池就会尽快执行改任务,ExecutorService提供了3个方法:
Future submit(Runnable task): 将一个Runnable对象提交给指定的线程池,线程池将在有空闲线程时执行Runnable对象代表的任务,其中
Future对象代表Runnable任务的返回值,但是run()方法没有返回值,所以Future对象将在run()方法执行后,返回null,但是可以调用Future的
isDone()、isCancelled()方法来获得Runnable对象的执行状态
Futuresubmit(Runnable task, T result): 将一个Runnable对象提交给指定的线程池,线程池将在有空闲线程时执行Runnable对象代表的任务,
其中Result显示的指定线程执行结束后的返回值,所以Future对象将在run()方法后返回result
Futuresubmit(Callabletask):将一个Callable对象提交给指定的线程池,线程池将在有空闲线程时执行Callable对象代表的任务,其中Future代
表Callable对象里call()方法的返回值
ScheduledExecutorService代表可在指定延迟后或周期性地执行线程任务的线程池,它提供了4个方法:
ScheduledFutureschedule(Callablecallable, long delay, TimeUnit unit):指定callable任务将在delay延迟后执行
ScheduledFutureschedule(Runnable command, long delay, TimeUnit unit):指定command任务将在delay延迟后执行
ScheduledFuturescheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):指定command任务将在delay延迟
后执行,在initialDelay后开始执行,一次在initialDelay+period、initialDelay+2*period…后重复执行,依次类推
ScheduledFuture scheduleWithFixedDealy(Runnable command, long initialDealy, long delay, TimeUnit unit):创建并执行一个在给定初始延迟
后启用的定期操作,随后在每一次执行终止和下一次执行开始之间都存在给定的延迟,如果任务在任意一次执行时遇到异常,就会取消后续执
行,否则只能通过程序来显示取消或者终止该任务
关闭线程池关闭线程池
用完一个线程池后,应该调用该线程池shutdown()方法,该方法将启动线程池的关闭序列,调用该方法后线程池不再接受新任务,但会将以前
所有已提交的任务执行完成,当线程池中的所有任务都执行完成后,池中的所有线程都会死亡
也可以调用线程池的shutdownNow()方法来关闭线程池,该方法会试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待
执行的任务列表
使用线程池步骤使用线程池步骤
调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池
创建Runnable实现类或Callable实现类的实例,作为线程执行任务
调用ExecutorService对象的submit()方法来提交Runnable实例或者Callable实例
当不想提交任何任务时,调用ExecutorService对象的shutdown()方法来关闭线程池
import java.util.concurrent.*;
public class ThreadPoolTest
{
public static void main(String[] args)
throws Exception
{
// 创建足够的线程来支持4个CPU并行的线程池
// 创建一个具有固定线程数(6)的线程池
ExecutorService pool = Executors.newFixedThreadPool(6);
// 使用Lambda表达式创建Runnable对象
Runnable target = () -> {