本文的出现是为了能够分享个人所学的相关知识,检验自身学习成果。内容会和其他技术存在部分关联,如有任何描述错误或者说明有误的地方,还望各位大佬指出。
1. 了解线程池
线程池简单理解就是一次创建多个线程,当一个任务交由线程池执行时,由线程池交由管理的线程来执行任务。
2. 线程池的优点
(1)不需要主动创建线程,线程的创建和销毁均由线程池管理,减少了不必要的消耗。
(2)提高响应速度,需要线程直接使用,省去了创建时的时间消耗。
(3)更方便于并发管理。
3. JDK中线程池类
说到线程池就需要去了解 Executors ,它是线程池的工厂类,里面对应了四种应用场景的线程池。
3.1 newFixedThreadPool
创建一个线程池,该线程池重用在共享的无边界队列上运行的固定数量的线程。
关键字
固定线程数、无边界阻塞队列
Executor threadPool = Executors.newFixedThreadPool(3);
// 调用
fixedPool.execute(()-> log.info("run with fixedPool"));
3.2 newSingleThreadExecutor
创建一个执行程序,该执行程序使用在不受限制的队列上操作的单个工作线程。
关键字
单个线程、无边界阻塞队列
Executor singlePool = Executors.newSingleThreadExecutor();
// 调用
singlePool.execute(() -> log.info("run with singlePool"));
3.3 newCachedThreadPool
创建一个线程池,该线程池根据需要创建新线程,但是将在先前构造的线程可用时重用它们。通过过期时间进行回收。
关键字
缓存、延迟销毁
Executor cachedPool = Executors.newCachedThreadPool();
// 调用
cachedPool.execute(() -> log.info("run with cachedPool"));
3.4 newScheduledThreadPool
创建一个线程池,该线程池可以安排命令在给定的延迟后运行或定期执行。
关键字
延迟执行、延迟队列
Executor scheduledPool = Executors.newScheduledThreadPool(2);
// 调用
scheduledPool.execute(() -> log.info("run with scheduledPool"));
4. 自定义线程池
如果好奇进去看过JDK定义的四种线程池,我们可以发现都是新建的ThreadPoolExecutor类,通过不同的参数实现不同的场景。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
参数 | 含义 | 作用 |
---|---|---|
corePoolSize | 线程池核心线程数 | corePoolSize –保留在池中的线程数(即使它们处于空闲状态),除非设置了allowCoreThreadTimeOut |
maximumPoolSize | 线程池最大线程数 | 池中允许的最大线程数 |
keepAliveTime | 线程存活时间 | 当线程数大于内核数时,这是多余的空闲线程将在终止之前等待新任务的最长时间。 |
unit | 线程存活时间单位 | keepAliveTime参数的时间单位 |
workQueue | 阻塞队列 | 用于在执行任务之前保留任务的队列。 此队列将仅保存execute方法提交的Runnable任务。 |
threadFactory | 线程工厂 | 根据需要创建新线程的对象。 |
handler | 线程池拒绝(饱和)策略 | 不能由ThreadPoolExecutor执行的任务的处理程序。默认使用AbortPolicy,及抛出异常。 |
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class MyThreadPool {
private static ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 8, 0
, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(8), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
@Test
public void testPool() {
for (int i = 0; i < 10; i++) {
int finalI = i;
pool.execute(() -> {
log.info(String.valueOf(finalI));
});
}
}
}
日志输出如下
