天天看點

日常随筆之線程池invokeAll使用風險

話不多說直接上代碼,invokeAll的使用方式如下圖

public class Main {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List<Callable<Integer>> tasks = new ArrayList<>();
        for( int i = 0; i < 10; i++) {
            tasks.add(()->{
                Random random = new Random();
                int second = random.nextInt(10);
                Thread.sleep(second * 1000) ;
                return second;
            });
        }
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        List<Future<Integer>> futures = executorService.invokeAll(tasks);
        for( int i = 0; i < futures.size(); i++) {
            System.out.println(futures.get(i).get());
        }

        executorService.shutdown();
    }
}           

invokeAll的作用是:等待所有的任務執行完成後統一傳回。

這裡與大家分享的是:如果executorService是公共線程池慎用,如果這時候有另外一個請求也不斷地往線程池裡不斷地方任務,這時候這個請求是不是就一直不停的阻塞了。

推薦寫法如下:

public class Main {

public static void main(String[] args) throws InterruptedException, ExecutionException, ExecutionException {

List<Future<Integer>> tasks = new ArrayList<>();

ExecutorService executorService = Executors.newFixedThreadPool(10);

for( int i = 0; i < 10; i++) {

Future<Integer> f = executorService.submit(() -> {

Random random = new Random();

int second = random.nextInt(10);

Thread.sleep(second * 1000);

return second;

});

tasks.add(f);

}

for( int i = 0; i < tasks.size(); i++) {

System.out.println(tasks.get(i).get());

executorService.shutdown();

}

}