目录
Executors 4种创建方式
(1)newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程。
(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行
(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行
线程池优点
(1)重用存在的线程,减少对象创建、消亡的开销,性能佳。
(2)可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
(3)提供定时执行、定期执行、单线程、并发数控制等功能。
不推荐使用Executors 创建线程池原因
(摘自阿里编码规约)
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors各个方法的弊端:1)newFixedThreadPool和newSingleThreadExecutor: 主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。2)newCachedThreadPool和newScheduledThreadPool: 主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
通过ThreadPoolExecutor创建线程池
ThreadPoolExecutor 是线程池的核心实现。线程的创建和终止需要很大的开销,线程池中预先提供了指定数量的可重用线程,所以使用线程池会节省系统资源,并且每个线程池都维护了一些基础的数据统计,方便线程的管理和监控。
7个核心参数
1. corePoolSize:线程池中的核心线程数,核心线程会一直存在,即使没有任务执行。
2. maximumPoolSize:线程池最大线程数 字面意思
3. keepAliveTime:当线程数大于核心数时,这是多余空闲线程在终止前等待新任务的最长时间。
4. unit:keepAliveTime的时间单位。
5. workQueue:任务队列,被提交但尚未被执行的任务(阻塞队列)
SynchronousQueue 直接提交队列 没有容量,每执行一个插入操作就会阻塞。一般不用
ArrayBlockingQueue 先进先出 基于数组的队列 读写锁不分离
LinkedBlockingQueue 先进先出 基于链表默认无界队列,使用必须给定大小 读写分离 效率高
PriorityBlockingQueue 可以设置优先级的队列
6. threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可。
7. handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数。
AbortPolicy:默认策略,在需要拒绝任务时抛出RejectedExecutionException;
CallerRunsPolicy:直接在 execute 方法的调用线程中运行被拒绝的任务,如果线程池已经关闭,任务将被丢弃;
DiscardPolicy:直接丢弃任务;
DiscardOldestPolicy:丢弃队列中等待时间最长的任务,并执行当前提交的任务,如果线程池已经关闭,任务将被丢弃。
创建线程池工具类
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* @author t
*/
public class ThreadUtils {
private static final Logger logger = LoggerFactory.getLogger(ThreadUtils.class);
public volatile static ThreadPoolExecutor threadPoolExecutor;
private final static String THREAD_NAME = "thread-t";
private final static String SINGLE_THREAD_NAME = "single-thread-t";
/**
* 获取线程工厂
*
* @return ThreadFactory
*/
public static ThreadFactory getThreadFactory(String threadName) {
return new ThreadFactoryBuilder()
.setNameFormat(threadName + "-%d")
.setUncaughtExceptionHandler((t, e) -> {
logger.error("线程报错", e);
})
// 守护线程
.setDaemon(true).build();
}
/**
* 获取线程池对象
*
* @return ExecutorService
*/
public static ThreadPoolExecutor getThreadPoolExecutor() {
try {
return new ThreadPoolExecutor(
4,
16,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
getThreadFactory(THREAD_NAME),
new ThreadPoolExecutor.AbortPolicy());
} catch (Exception e) {
logger.error("创建线程池发生异常", e);
}
return threadPoolExecutor;
}
/**
* 获取单利线程池对象
*
* @return ExecutorService
*/
public static ExecutorService getSingleThreadPoolExecutor() {
try {
if (threadPoolExecutor == null) {
synchronized (ThreadUtils.class) {
if (threadPoolExecutor == null) {
threadPoolExecutor = new ThreadPoolExecutor(
10,
20,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
getThreadFactory(SINGLE_THREAD_NAME),
new ThreadPoolExecutor.AbortPolicy());
}
}
}
} catch (Exception e) {
logger.error("创建单例线程池发生异常", e);
}
return threadPoolExecutor;
}
}