并发之线程池(二)

2021-04-14  本文已影响0人  简楼

前言

使用过线程池的我们都知道,创建线程池尽量使用 ThreadPoolExecutor
小提一句,在springboot中推荐使用 ThreadPoolTaskExecutor,该方法是对 ThreadPoolExecutor进行了再一次封装;

image.png

那么为什么要使用 ThreadPoolExecutor创建线程池呢?
在此之前,我们先了解下 Executors 创建线程池的特点;

固定数目线程的线程池:newFixedThreadPool

源码:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

特点:

工作流程

newFixedThreadPool工作流程.png

注意:使用无界队列的线程池会导致内存飙升,因为newFixedThreadPool使用了无界的阻塞队列LinkedBlockingQueue,如果线程获取一个任务后,任务的执行时间比较长,会导致队列的任务越积越多,导致机器内存使用不停飙升, 最终导致OOM;

使用场景

newFixedThreadPool 适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务;

可缓存线程的线程池:newCachedThreadPool

源码:

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

特点:

工作流程

newCachedThreadPool工作流程.png

使用场景

用于并发执行大量短期的小任务;

单线程的线程池:newSingleThreadExecutor

源码:

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

特点:

工作流程

newSingleThreadExecutor工作流程.png

使用场景

适用于串行执行任务的场景,一个任务一个任务地执行;

定时及周期执行的线程池:newScheduledThreadPool

源码:

public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }

特点:

工作流程

newScheduledThreadPool工作流程.png

使用场景

定时和周期性任务场景,需要限制线程数量的场景;

总结

这几种常用的线程池创建,在参数设置上,各有利弊,并不一定适合自己当前的系统,弊端的话,阿里的java规范已经很清楚的告诉我们了;
同时使用以上的创建方式是不够灵活的,所以我们在使用线程时尽量使用ThreadPoolExecutor去创建线程池,按照自己系统的配置去合理设置。

上一篇 下一篇

猜你喜欢

热点阅读