1.线程池的处理流程
注意点:核心线程池已满时需要将任务加入阻塞队列,如果阻塞队列满才看线程池的最大线程数量
2. 线程池可选择的阻塞队列
public void blockingQueueTest(){
/**
* 基于数组的有界的阻塞队列,容量为10
*/
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
/**
* 基于链表的 无界(不传值的构造函数) / 有界 (传参) 的阻塞队列
*/
LinkedBlockingDeque<Integer> linkedBlockingDeque = new LinkedBlockingDeque<>();
}
@Test
public void synchronousQueue() throws InterruptedException {
/**
* 同步移交阻塞队列,没有存储数据的能力, 一对一的队列, 基于线程的,一个线程插入,一个线程移除
*/
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
// 构建插入值的线程
new Thread(() -> {
try {
queue.put(1);
System.out.println("插入成功");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
/* 注释后, 无 插入成功打印, 因为该队列是一对一的方式
// 删除值
new Thread(() -> {
try {
queue.take();
System.out.println("删除成功");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
*/
Thread.sleep(1000L * 10);
}
3. 线程池可选择的饱和策略
注:阻塞队列和最大线程池已经满后
4. 线程池执行示意图
5. 线程池提交任务
// 1. submit方法, 可以接收任务的返回结果,接收到结果后继续执行
public void submitTest() throws ExecutionException, InterruptedException {
// 创建线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
/**
* 使用 submit 方法提交任务,接收任务的返回结果
*/
Future<Integer> future = threadPool.submit(() -> {
Thread.sleep(1000L * 10);
return 2 * 5;
});
/**
* 阻塞方法,需要得到返回值后才继续执行
*/
Integer integer = future.get();
System.out.println("执行结果是: " + integer);
}
// 2. execute方法,提交任务, 没有返回值
public void executeTest() throws InterruptedException {
// 创建线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
// execute 提交任务, 没有返回值
threadPool.execute(() ->{
try {
Thread.sleep(1000L * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Integer num = 2 * 5;
System.out.println("执行结果:" + num);
});
Thread.sleep(1000L * 1000);
}
6. 线程池的状态
注: shutdown 方法 与 shutdownNow方法
7. 演示线程池的四种饱和策略
public class PolicyTest {
// 创建一个线程池
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
// 核心线程2 最大线程3
2, 3,
// 有界的阻塞队列
60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5));
/**
* 任务
*/
class Task implements Runnable{
/**
* 任务名称
*/
private String taskName;
public Task(String taskName){
this.taskName = taskName;
}
@Override
public void run() {
// 线程执行方法
System.out.println("线程["+ Thread.currentThread().getName() +"]正在执行["
+ taskName + "]任务...");
try {
Thread.sleep(1000L*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程["+ Thread.currentThread().getName() +"]已经执行完["
+ taskName + "]任务!!!");
}
}
/**
* 线程池的执行过程:
* 2 个核心线程
* 5 个任务队列
* 3 个最大线程:除核心线程后 1个线程可用
*
* 前2个任务,占用核心线程执行
* 第3 到 第7个任务,会暂存到任务队列中
* 第8个任务 启动最大线程执行
*
* 第9个任务,没有线程执行,会启动饱和策略执行
*/
/**
* 单元测试执行完,主线程等待100秒,防止主线程退出
*/
@After
public void after() throws InterruptedException {
Thread.sleep(1000L * 100);
}
}
7.1 终止饱和策略
/**
* 终止策略,拒接任务提交
*/
@Test
public void abortPolicyTest(){
// 设置饱和策略为 终止策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
执行结果:
7.2 丢弃策略
@Test
public void discardPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
执行结果:
7.3 丢弃旧任务策略
/**
* 抛弃旧任务策略
* TODO 丢弃掉任务队列中的旧任务,暂存新提交的任务
*/
@Test
public void discardOldestPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
执行结果:
7.4 调用者运行策略
/**
* 调用者运行策略
* TODO 借用主线程来执行多余任务
*/
@Test
public void callerRunsPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
执行结果:
所有测试代码
public class PolicyTest {
// 创建一个线程池
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
// 核心线程2 最大线程3
2, 3,
// 有界的阻塞队列
60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5));
/**
* 任务
*/
class Task implements Runnable{
/**
* 任务名称
*/
private String taskName;
public Task(String taskName){
this.taskName = taskName;
}
@Override
public void run() {
// 线程执行方法
System.out.println("线程["+ Thread.currentThread().getName() +"]正在执行["
+ taskName + "]任务...");
try {
Thread.sleep(1000L*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程["+ Thread.currentThread().getName() +"]已经执行完["
+ taskName + "]任务!!!");
}
}
/**
* 线程池的执行过程:
* 2 个核心线程
* 5 个任务队列
* 3 个最大线程:除核心线程后 1个线程可用
*
* 前2个任务,占用核心线程执行
* 第3 到 第7个任务,会暂存到任务队列中
* 第8个任务 启动最大线程执行
*
* 第9个任务,没有线程执行,会启动饱和策略执行
*/
/**
* 终止策略,拒接任务提交
*/
@Test
public void abortPolicyTest(){
// 设置饱和策略为 终止策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
@Test
public void discardPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
/**
* 抛弃旧任务策略
* TODO 丢弃掉任务队列中的旧任务,暂存新提交的任务
*/
@Test
public void discardOldestPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
/**
* 调用者运行策略
* TODO 借用主线程来执行多余任务
*/
@Test
public void callerRunsPolicyTest(){
// 设置饱和策略为 丢弃策略,丢弃最后的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 创建线程执行
for (int i = 1; i <= 10 ; i++) {
try {
executor.execute(new Task("线程任务" + i));
}catch (Exception e){
System.err.println(e);
}
}
// 线程池关闭
executor.shutdown();
}
/**
* 单元测试执行完,主线程等待100秒,防止主线程退出
*/
@After
public void after() throws InterruptedException {
Thread.sleep(1000L * 100);
}
}