线程池创建方式
一、Executors
1、newFixedThreadPool
1.1 创建固定大小的线程池。
1.2 创建方式:ExecutorService fixedTp= Executors.newFixedThreadPool(int count);
1.3 适用场景:执行长期的任务
2、newCachedThreadPool
2.1 创建一个不限线程数上限的线程池,任何提交的任务都将立即执行
2.2 创建方式:ExecutorService cachedTp = Executors.newCachedThreadPool();
2.3 适用场景:执行很多短期异步的小程序或者负载较轻的服务器
3、newSingleThreadExecutor
3.1 创建只有一个线程的线程池,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
3.2 创建方式:ExecutorService SingleTp = Executors.newSingleThreadExecutor();
3.3 适用场景:一个任务一个任务执行的场景
4、newScheduledThreadPool
4.1 创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
4.2 创建方式:ScheduledExecutorService schedTp= Executors.newScheduledThreadPool(5);
4.3 适用场景:周期性执行任务的场景
创建一个定长的线程池,线程池可以周期性或延迟执行如下:
(1) scheduledTp.schedule(r1, 5, TimeUnit.SECONDS);//延迟3秒后执行r1
(2) scheduledTp.scheduleAtFixedRate(r2,5,3,TimeUnit.SECONDS);//延迟5秒后每3秒执行一次r2
二、ThreadPoolExecutor
Executors创建线程池的快捷方法,实际上是调用了ThreadPoolExecutor的构造方法
public ThreadPoolExecutor(
int corePoolSize, // 线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。
int maximumPoolSize, // 线程数的上限
long keepAliveTime, TimeUnit unit, // 超过corePoolSize的线程的idle时长,
// 超过这个时间,多余的线程会被回收。
BlockingQueue<Runnable> workQueue, // 任务的排队队列
ThreadFactory threadFactory, // 新线程的产生方式
RejectedExecutionHandler handler) // 拒绝策略
举例:
ExecutorService executorService = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(512), // 使用有界队列,避免OOM
new ThreadPoolExecutor.DiscardPolicy());//DiscardPolicy 对溢出队列的任务不做处理,直接忽略
其他拒绝策略
AbortPolicy 抛出RejectedExecutionException(默认)
DiscardOldestPolicy 丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置
CallerRunsPolicy 直接由提交任务者执行这个任务
三、两种线程池创建方式的异同
1、Executors.newXXXThreadPool()快捷方法创建线程池,这种方式使用无界的任务队列,容易造成OOM
建议使用ThreadPoolExecutor的构造方法手动指定各项参数。
2、提交任务的类型分为Runnable和Callable 二者区别如下:
2.1 方法签名不同,void Runnable.run(), V Callable.call() throws Exception
2.2 是否允许有返回值,Callable允许有返回值
2.3 是否允许抛出异常,Callable允许抛出异常。
提交任务的方式:
Future<T> submit(Callable<T> task) 有返回值
void execute(Runnable command) 无返回值
Future<?> submit(Runnable task) 虽然返回Future,但是其get()方法总是返回null
四、一个简单实例
private static ExecutorService executor = new ThreadPoolExecutor(0, 16,
60000L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(10240),
new ThreadFactoryBuilder().setNameFormat("feed-push-thread-%d").build(),
new ThreadPoolExecutor.AbortPolicy());
executor.submit(()->{
//执行对应的逻辑
});