美文网首页
线程池相关-线程池的创建

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

作者: Murray66 | 来源:发表于2019-04-03 14:42 被阅读0次

本文学习过程中持续更新

线程池的创建

为什么不推荐用 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个参数,参数如下:

  • corePoolSize: 除非设置了 允许核心线程超时的最大时间,否则即使线程处于空闲状态,也要保留在池中的线程数
  • maximumPoolSize: 线程池维护线程的最大数量
  • keepAliveTime: 当线程数大于核心时,这是多余空闲线程在终止之前等待新任务的最长时间
  • unit: 上述时间的单位
  • workQueue: 在执行任务之前用于保存任务的缓冲队列,此队列仅包含 excute 方法提交的 Runnable 任务

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

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

excute 的执行逻辑大概如下:

  • 当池中线程数量少于 corePoolSize,创建一个新线程去执行任务
  • 当池中线程数量等于 corePoolSize,如果缓冲队列 workQueue 未满,放入缓冲队列
  • 如果缓冲队列满,线程池数量小于 maximumPoolSize, 建新的线程来处理任务
  • 如果创建新的线程来处理任务失败,说明线程池数量饱和,即达到了maximumPoolSize,会拒绝这次任务

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 的方式创建线程池,手动设置各种参数(包括最大线程数、缓冲队列的最大长度)。

相关文章

  • 线程池创建和相关知识

    线程池创建(单例):Android线程池得要这么用 - 简书 线程池相关知识:Android开发之线程池使用总结 ...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • 阿里巴巴Java高级岗必问面试题总结:JVM+多线程+网络+Re

    阿里巴巴Java高级岗必问面试题总结 一、Java多线程相关 线程池的原理,为什么要创建线程池?创建线程池的方式;...

  • java线程池源码解析

    主要介绍线程池相关知识,关于线程池,首先我们思考下为什么要用线程池。如果单纯的使用线程,线程的创建和销毁都是自己来...

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

    本文学习过程中持续更新 线程池的创建 为什么不推荐用 Executors 创建线程池,而是用 ThreadPool...

  • 线程池

    线程池 a. 基本组成部分: 1、线程池管理器(ThreadPool):用于创建并管理线程池,包括创建线程池,销毁...

  • 线程池的基本知识

    线程池的四个组成部分: 1.线程池管理器:用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;2.工作...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • ThreadPoolExecutor

    1 创建线程池 通过ThreadPoolExecutor创建线程池: corePoolSize:核心线程的数量。m...

  • spring 线程池和java线程池

    jdk线程池就是使用jdk线程工具类ThreadPoolExecutor 创建线程池spring线程池就是使用自己...

网友评论

      本文标题:线程池相关-线程池的创建

      本文链接:https://www.haomeiwen.com/subject/ifczbqtx.html