线程池的核心实现类是ThreadPoolExecutor,可以通过它来创建一个线程池,其参数最多的构造方法如下:
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.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }参数的作用要说明一下 corePoolSize:核心线程数。默认情况下线程池是空的,只有提交任务才会创建线程,如果当前运行的线程数少于corePoolSize,则创建新线程来处理任务;如果调用线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有核心线程来等待任务。 maximumPoolSize:允许创建的最大线程数。如果任务队列满了并且线程数小于maximumPoolSize时,会创建新的线程来处理任务。 keepAliveTime:非核心线程闲置的超时时间。超过这个时间则回收。设置allowCoreThreadTimeOut属性true时,keepAliveTime也会应用到核心线程上。 TimeUnit:keepAliveTime参数的时间单位。可选的有天,小时,分钟,秒,毫秒。 workQueue:任务队列。如果当前线程数大于corePoolSize,则将任务添加到此任务队列中。此队列是BlockingQueue类型阻塞队列。 threadFactory:线程工厂。可以用线程工厂给每个创建出来的线程设置名字。 RejectedExecutionHandler:饱和策略。当任务队列和线程池都满了时所采取的应对策略,默认是AbortPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常。此外还有三种策略:
CallerRunsPolicy: 用调度者所在的线程来处理任务。提供简单的反馈控制机制,减缓新任务的提交速度。DiscardOldestPolicy: 不能执行的任务,并将该任务删除。DiscardPolicy:抛弃队列最近的任务,并执行当前的任务。线程池的处理流程: 提交任务后,线程池先判断是否达到了核心线程数。如果未达到核心线程数,则创建核心线程处理任务。 接着线程池判断任务队列是否满了。如果没有满,则将任务添加到任务队列。 如果任务队列满了,线程池判断线程数是否达到最大线程数。如果未达到就创建非核心线程处理任务。否则,执行饱和策略。
Executors提供了静态方法,创建常用的4种线程池。 FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }可重用固定线程数的线程池,核心线程和最大线程数相同,意味着只有固定数量的核心线程,任务队列采用无界阻塞队列LinkedBlockingQueue。
CachedThreadPool
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }根据需要创建线程的线程池,corePoolSize为0,maximumPoolSize为Integer.MAX_VALUE,意味着没有核心线程,非核心线程是无界的。空闲线程等待任务的最长时间为60s,阻塞队列SynchronousQueue,塌不存储元素,每个插入操作必须等待另一个线程的移除操作。适用于大量的需要立即处理并且耗时较少的任务。
SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }单个工作线程的线程池,能确保所有的任务在一个线程中按顺序逐一执行。
ScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); }一个能实现定时和周期性任务的线程池,ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,主要用于给定延时之后的运行任务或定期处理任务。
向线程池提交任务时可以使用execute和submit,区别就是submit可以返回一个future对象,通过future对象可以了解任务的执行情况,可以取消任务的执行,还可以获取执行结果或者执行异常。