Executor 如何使用?
Executor 英文意思是执行者,可以看出它的作用是提交和执行任务接口,也可以理解为是线程池。
Executor 有一个子接口 ExecutorService,ExecutorService 可以管理和终止任务的方法,可以追踪异步任务的进度的 Executor。
Executors 是线程池的工厂类,提供静态工具方法。使用 Executors 可以方便地创建各种类型的线程池。但是由于 Executors 创建的线程池内部很多地方用到了无界任务队列,在高并发场景下,无界任务队列会接收过多的任务对象,导致 JVM 抛出OutOfMemoryError,整个 JVM 服务崩溃,影响严重。所以很多公司已经不建议使用 Executors 去创建线程。
简单介绍下 Executors 的使用:
newFixedThreadPool:创建定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
newCachedThreadPool:创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
newScheduledThreadPool:创建定长线程池,可执行周期性的任务
newSingleThreadExecutor:创建单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
newSingleThreadScheduledExecutor:创建单线程可执行周期性任务的线程池
newWorkStealingPool:任务可窃取线程池,不保证执行顺序,当有空闲线程时会从其他任务队列窃取任务执行,适合任务耗时差异较大
JDK 提供的线程池相关的工具类中,最核心的是 ThreadPoolExecutor。它最复杂的构造函数有 7 个参数:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, hreadFactory threadFactory, RejectedExecutionHandler handler)
参数说明:
corePoolSize:线程池保有的最小线程数 maximumPoolSize:线程池创建的最大线程数 keepAliveTime:一个线程空闲了 keepAliveTime * unit 这么长时间,且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了 unit:keepAliveTime 的时间单位 workQueue:任务队列 threadFactory:线程工厂对象,可以自定义如何创建线程,如给线程指定 name handler:自定义任务的拒绝策略。线程池中所有线程都在忙碌,且任务队列已满,线程池就会拒绝接收再提交的任务。handler 就是拒绝策略,包括 4 种(即 RejectedExecutionHandler 接口的 4个实现类) AbortPolicy:默认的拒绝策略,throws RejectedExecutionException CallerRunsPolicy:提交任务的线程自己去执行该任务 DiscardPolicy:直接丢弃任务,不抛出任何异常 DiscardOldestPolicy:丢弃最老的任务,加入新的任务
使用示例:
package constxiong.interview; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 测试 ThreadPoolExecutor 创建线程池 * @author ConstXiong */ public class TestThreadPoolExecutor { public static void main(String[] args) { testSubmitTask(); } /** * 测试使用 ThreadPoolExecutor 创建线程池,并向线程池提交任务 */ private static void testSubmitTask() { int corePoolSize = 1;//最小线程数 int maximumPoolSize = 2;//最大线程数 long keepAliveTime = 1000L;//1000个单位时间 Executor exector = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(),//可以修改队列:有界队列、无界队列、有优先级的队列 Executors.defaultThreadFactory(),//线程工程对象,可以定义如何创建线程 new ThreadPoolExecutor.AbortPolicy()); //任务队列已满,线程池决绝策略 for (int i = 0; i < 5; i++) { exector.execute(() -> { System.out.println(Thread.currentThread().getName()); }); } } }
- Java 自学经历
- Java 面试题 H5
- Java 面试题小程序