1. 什么是线程池?
线程池是一种多线程解决模式,解决过程中将工作增加到队列,而后在创立线程后主动启动这些工作。线程池线程都是后盾线程。每个线程都应用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中闲暇(如正在期待某个事件), 则线程池将插入另一个辅助线程来使所有处理器放弃忙碌。如果所有线程池线程都始终保持忙碌,但队列中蕴含挂起的工作,则线程池将在一段时间后创立另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程能够排队,但他们要等到其余线程实现后才启动。
2. 常见的线程池
2.1 newCachedThreadPool
创立一个可缓存线程池,如果线程池长度超过解决须要,可灵便回收闲暇线程,若无可回收,则新建线程。
这种类型的线程池特点是:
工作线程的创立数量简直没有限度 (其实也有限度的, 数目为 Interger. MAX_VALUE), 这样可灵便的往线程池中增加线程。
如果长时间没有往线程池中提交工作,即如果工作线程闲暇了指定的工夫 (默认为 1 分钟),则该工作线程将主动终止。终止后,如果你又提交了新的工作,则线程池从新创立一个工作线程。
在应用 CachedThreadPool 时,肯定要留神管制工作的数量,否则,因为大量线程同时运行,很有会造成零碎瘫痪。
2.2 newFixedThreadPool
创立一个指定工作线程数量的线程池。每当提交一个工作就创立一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的工作存入到池队列中。
FixedThreadPool 是一个典型且优良的线程池,它具备线程池进步程序效率和节俭创立线程时所耗的开销的长处。然而,在线程池闲暇时,即线程池中没有可运行工作时,它不会开释工作线程,还会占用肯定的系统资源。
2.3 newSingleThreadExecutor
创立一个单线程化的 Executor,即只创立惟一的工作者线程来执行工作,它只会用惟一的工作线程来执行工作,保障所有工作依照指定程序 (FIFO, LIFO, 优先级) 执行。如果这个线程异样完结,会有另一个取代它,保障程序执行。单工作线程最大的特点是可保障程序地执行各个工作,并且在任意给定的工夫不会有多个线程是流动的。
2.4 newScheduleThreadPool
创立一个定长的线程池,而且反对定时的以及周期性的工作执行,反对定时及周期性工作执行。
3.5 下图可见 newScheduleThreadPool 线程池是 ThreadPoolExecutor 的子类,所以本章将围绕 ThreadPoolExecutor 线程池去做详解。
ThreadPoolExecutor 详解
进入 ThreadPoolExecutor 类中,能够看到,创立这个线程池,有四种形式,且全是有参结构。
查看全参结构
- corePoolSize:外围线程池大小
- maximumPoolSize:容许线程池同时并行的线程数量
- keepAliveTime:当线程数大于内核数时,这是多余的闲暇线程将在终止之前期待新工作的最长工夫
- unit:TimeUnit 类型,这没什么好说
- workQueue:在执行工作之前用于保留工作的队列,此队列将仅保留 execute 办法提交的 Runnable 工作。
- threadFactory:执行程序创立新线程时要应用的工厂
- handler:当线期待队列中的数量超过既定容量,所须要解决策略
综上所述,咱们做异步的话,不须要回绝策略,所以,咱们抉择没有回绝策略参数的构造方法去创立。
1. 初始化线程池
@Component
public class ThreadPoolStarter {@Value("${thread-pool.corePoolSize:2}")
private Integer corePoolSize;
@Value("${thread-pool.maxPoolSize:3}")
private Integer maximumPoolSize;
@Value("${thread-pool.queueSize:10}")
private Integer queueSize;
@Value("${thread-pool.keepAliveTime:600}")
private Long keepAliveTime;
private TimeUnit unit = TimeUnit.SECONDS;
@Bean("workerPool")
public ThreadPoolExecutor threadPool() {
// 线程工厂
ThreadFactory threadFactory = new CustomizableThreadFactory("worker-pool-");
// 初始化线程池
return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
unit, new LinkedBlockingQueue<>(queueSize), threadFactory);
}
}
2. 创立线程类实现 runnable 接口
/**
* @description
* @author: yzr
* @date: 2021-06-02 11:12
**/
public class ThreadRunner implements Runnable {
@Override
public void run() {
try {log.info("我要睡眠了");
Thread.sleep(5000);
} catch (InterruptedException e) {e.printStackTrace();
}
log.info("我的业务办法");
}
}
3. 测试, 注入线程池,并把线程交由线程池去解决。
@SpringBootTest(classes = CasbinApplication.class)
@Slf4j
public class SpringBootTestTest {
@Autowired
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
ThreadRunner threadRunner;
@Test
public void test() {log.info("开始了");
threadPoolExecutor.execute(threadRunner);
log.info("完结了");
}
}
4. 执行并查看后果
由此可见咱们的异步调用胜利了