Executor 如何使用?

2019-12-30   阅读(124)  

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());
			});
		}
	}
	
}

 

ConstXiong 备案号:苏ICP备16009629号-3