Executor线程池

文章目录

  • Executor的UML图:(常用的几个接口和子类)
  • 一般使用Executors提供的静态工厂方法创建线程池:
  • 阿里巴巴规范
  • 创建线程的正确方法:
  • ThreadPoolExecutor构造函数的各个参数说明
  • 参考文献:

Executor的UML图:(常用的几个接口和子类)

Executor线程池_第1张图片
Executors(C)->…各种静态方法(实际上调用ThreadPoolExecutor)

一般使用Executors提供的静态工厂方法创建线程池:

  • newCachedThreadPool();创建一个可缓存的线程池,调用execute将重用以前创建的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有60秒未被使用的线程。
  • newFixedThreadPool(int nThreads);创建固定数目的线程池。
  • newSingleThreadExecutor();创建单线程化的Executor。
  • newSingleThreadScheduledExecutor() 和 newScheduledThreadPool(int corePoolSize);
    创建一个支持定时以及周期性任务执行的线程池。区别在单一工作线程还是多工作线程。
  • newWorkStealingPool(int parallelism);并行处理任务,不保证处理顺序。

在大多数应用场景下,使用 Executors 提供的 5 个静态工厂方法就足够了,但是仍然可能
需要直接利用 ThreadPoolExecutor 等构造函数创建,这就要求你对线程构造方式有进一
步的了解,你需要明白线程池的设计和结构。

阿里巴巴规范

线程池不允许用Executors去创建,而是通过ThreadPoolExecutor的方式,能更加明确线程池的运行规则,规避资源耗尽的风险。
Executor返回的线程对象的弊端:

  • FiexdThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求,从而导致OOM。
  • CachedThreadPool和ScheduleThreadPool:允许创建的线程数量为Integer.Max_VAlue,可能会创建大量线程,从而导致OOM。

java中BlockingQueue主要有两种实现,分别是ArrayBlockingQueue和LinkedBlockingQueue。ArrayBlockingQueue是一个用数组实现的有界阻塞队列,必须设置容量。而LinkedBlockingQueue是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE。

创建线程的正确方法:

避免使用Executors创建线程池,主要是避免使用其中的默认实现。我们可以直接调用ThreadPoolExecutor的构造函数自己创建线程池。在创建的同时,给BlockQueue指定容量就可以了。

private static ExecutorService executor = new ThreadPoolExecutor(10, 10,
        60L, TimeUnit.SECONDS,
        new ArrayBlockingQueue(10));

这种情况下,一旦提交的线程数超过当前最大可用线程数+队列容量时,就会抛出java.util.concurrent.RejectedExecutionException,这是因为当前线程池使用的队列是有界边界队列,队列已经满了便无法继续处理新的请求。但是异常(Exception)总比发生错误(Error)要好。

ThreadPoolExecutor构造函数的各个参数说明

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) //后两个参数为可选参数
  • corePoolSize:核心线程数,如果运行的线程少于corePoolSize,则创建新线程来执行新任务,即使线程池中的其他线程是空闲的。
  • maximumPoolSize:最大线程数,可允许创建的线程数,corePoolSize和maximumPoolSize设置的边界自动调整池大小:仅当队列满时才创建新线程。
  • keepAliveTime:如果线程数多于corePoolSize,则这些多余的线程的空闲时间超过keepAliveTime时将被终止。
  • unit:keepAliveTime参数的时间单位。
  • workQueue:保存任务的阻塞队列,与线程池的大小有关:
    • 当运行的线程数少于corePoolSize时,在有新任务时直接创建新线程来执行任务而无需再进队列。
    • 当运行的线程数等于或多于corePoolSize,在有新任务添加时则选加入队列,不直接创建线程。
    • 当队列满时,在有新任务时就创建新线程。
  • threadFactory:使用ThreadFactory创建新线程,默认使用defaultThreadFactory创建线程。
  • handle:定义处理被拒绝任务的策略,默认使用ThreadPoolExecutor.AbortPolicy,任务被拒绝时将抛出RejectExecutorException。

参考文献:

  • https://www.cnblogs.com/MOBIN/p/5436482.html
  • https://blog.csdn.net/u010321349/article/details/83927012

你可能感兴趣的:(Java,多线程)