线程池相关-线程池的创建

2019-04-03  本文已影响0人  Murray66

本文学习过程中持续更新

线程池的创建

为什么不推荐用 Executors 创建线程池,而是用 ThreadPoolExecutor 的方式?

通过 Executors 创建,以 FixedThreadPool 举例

ExecutorService exec = Executors.newFixedThreadPool(thread_num)

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

会创建一个 ThreadPoolExecutor

在这里的构造方法里,传5个参数,参数如下:

当然,这只是 ThreadPoolExecutor 的构造方法之一,ThreadPoolExecutor 还有更多参数的构造方法,这里先不谈。

再来到 excute 方法,该方法用于执行提交的 Runnable 任务。

excute 的执行逻辑大概如下:

ThreadPoolExecutor 中,还有一个 RejectedExecutionHandler 用来对拒绝的任务进行处理,这里先不谈。

excute 的执行方法中可以看到,缓冲队列也有个饱和值,这个值是可以由我们自己设置的。

举个例子,直接使用 ThreadPoolExecutor 创建的时候:

int count = 100;
ThreadPoolExecutor tp = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(count));

而上文中,用 Executors 创建 FixedThreadPool


ExecutorService exec = Executors.newFixedThreadPool(thread_num)

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

这里的缓冲队列初始化方法是这样的:

/**
     * Creates a {@code LinkedBlockingQueue} with a capacity of
     * {@link Integer#MAX_VALUE}.
     */
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

允许缓冲队列的长度为 Integer.MAX_VALUE,这时可能会堆积大量的请求,有OOM风险。
创建 SingleThreadExecutor与之同理,存在缓冲队列堆积大量请求风险。

Executors 创建 CachedThreadPool :

ExecutorService exec = Executors.newCachedThreadPool();

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

允许创建的线程数量为 Integer.MAX_VALUE,会堆积大量的线程,有OOM风险。
创建 ScheduledThreadPool 与之同理,有堆积大量线程的风险。

所以推荐用 ThreadPoolExecutor 的方式创建线程池,手动设置各种参数(包括最大线程数、缓冲队列的最大长度)。

上一篇 下一篇

猜你喜欢

热点阅读