Java线程池使用不当引发的阻塞问题

将下面TestThreadPool代码中改为使用同一个线程池即可复现问题。
注:可以调用CompletableFuture的带超时时间的get方法,避免长时间执行等待。


image.png

1、引入guava依赖

        
            com.google.guava
            guava
            20.0
        

2、代码示例

package com.example.demo;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThreadPool {

    private static final ThreadPoolExecutor MAIN_THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("main-pool-thread-%d").build(), new ThreadPoolExecutor.CallerRunsPolicy());
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("sub-pool-thread-%d").build(), new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) {
        System.out.println("start------------");
        try {
            List> list = new ArrayList<>();
            for(int i = 1; i <= 3; i++){
                list.add(getMainCompletableFuture("主任务"+i));
            }
            CompletableFuture.allOf(list.toArray(new CompletableFuture[0])).get();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("end------------");
        MAIN_THREAD_POOL_EXECUTOR.shutdown();
        THREAD_POOL_EXECUTOR.shutdown();
    }

    public static CompletableFuture getMainCompletableFuture(String name){
        return CompletableFuture.supplyAsync(() -> {
            System.out.println(name+",开始--" + Thread.currentThread().getName());
            Integer res = getSubTask(name);
            System.out.println(name+",结束--" + Thread.currentThread().getName());
            return res;
        },MAIN_THREAD_POOL_EXECUTOR);
    }

    public static Integer getSubTask(String parentName) {
        try {
            List> list = new ArrayList<>();
            for(int i = 1; i <= 3; i++){
                list.add(getSubCompletableFuture(parentName+"-子任务"+i));
            }
            CompletableFuture.allOf(list.toArray(new CompletableFuture[0])).get();
        } catch (Exception e){
            e.printStackTrace();
        }
        return 1;
    }

    public static CompletableFuture getSubCompletableFuture(String name){
        return CompletableFuture.supplyAsync(() -> {
            System.out.println(name + ",开始--" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + ",结束--" + Thread.currentThread().getName());
            return 1;
        },THREAD_POOL_EXECUTOR);
    }
}
image.png

你可能感兴趣的:(Java线程池使用不当引发的阻塞问题)