ThreadPoolExecutor 最基础的线程池

在Java中,线程池的概念是Executor这个接口,具体实现为ThreadPoolExecutor类,学习Java中的线程池,就能够直接学习他了,对线程池的配置,就是对ThreadPoolExecutor构造函数的参数的配置。java

//五个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)
 
//六个参数的构造函数-1
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory)
 
//六个参数的构造函数-2
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler)
 
//七个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
  • int corePoolSize => 该线程池中核心线程数最大值
线程池新建线程的时候,若是当前线程总数小于corePoolSize,则新建的是核心线程,若是超过corePoolSize,则新建的是非核心线程

核心线程默认状况下会一直存活在线程池中,即便这个核心线程啥也不干(闲置状态)。

若是指定ThreadPoolExecutor的allowCoreThreadTimeOut这个属性为true,那么核心线程若是不干活(闲置状态)的话,超过必定时间(时长下面参数决定),就会被销毁掉

很好理解吧,正常状况下你不干活我也养你,由于我总有用到你的时候,但有时候特殊状况(好比我本身都养不起了),那你不干活我就要把你干掉了
  • int maximumPoolSize 该线程池中线程总数最大值函数

  • long keepAliveTime TimeUnit unit 该线程池中非核心线程闲置超时时长,一个非核心线程,若是不干活(闲置状态)的时长超过这个参数所设定的时长,就会被销毁掉学习

  • BlockingQueue<Runnable> workQueue 见 这里.net

  • ThreadFactory threadFactory 当须要建立一个新的线程时,会调用该方法。线程

  • RejectedExecutionHandler handler 这里想对拒绝策略,在使用线程池而且使用有界队列的时候,若是队列满了,任务添加到线程池的时候就会有问题,针对这些问题java线程池提供了如下几种策略:code

    1. AbortPolicy 该策略是线程池的默认策略。使用该策略时,若是线程池队列满了丢掉这个任务而且抛出RejectedExecutionException异常。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             //不作任何处理,直接抛出异常
             throw new RejectedExecutionException("Task " + r.toString() +
                                                  " rejected from " +
                                                  e.toString());
         }
    1. DiscardPolicy 这个策略和AbortPolicy的slient版本,若是线程池队列满了,会直接丢掉这个任务而且不会有任何异常。
    2. DiscardOldestPolicy 丢弃最老的。也就是说若是队列满了,会将最先进入队列的任务删掉腾出空间,再尝试加入队列。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             if (!e.isShutdown()) {
             	//移除队头元素
                 e.getQueue().poll();
                 //再尝试入队
                 e.execute(r);
             }
         }
    1. CallerRunsPolicy若是添加到线程池失败,那么主线程会本身去执行该任务,不会等待线程池中的线程去执行。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             if (!e.isShutdown()) {
                 //直接执行run方法
                 r.run();
             }
         }
    1. 自定义

PS: 不少文章里并不关注拒绝策略,可是实际上,在开发过程当中咱们须要想象,若是线程被拒绝咱们应该怎么处理。blog

java线程池类

线程池最基础的类是Executor 是一个接口,只定义了一个execute,方法,表示运行一个Runnable。继承

public interface Executor {
    void execute(Runnable command);
}

而后是 ExecutorService 它也是一个接口,继承了 Executor,在此基础上主要提供了shutdown和submit能力。shutdown用于控制线程池中止,submit相似于execute,可是提供了Future支持(带返回值)。接口

而后就是虚类 AbstractExecutorService 继承了 ExecutorService 实现一些默认方法。队列

再上层就是ThreadPoolExecutor 实现了 AbstractExecutorService。

常见线程池

Executors类中提供了一些默认特性的线程池,再加上自定义 ThreadPoolExecutor 基本上就够用了。

  • FixedThreadPool 定长线程池,超出的线程会在队列中等待(maximumPoolSize值至关于无效)
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • CachedThreadPool 很是任性的线程池,有空闲用空闲没空闲直接起线程,不会等待。maximumPoolSize 是 Integer.MAX_VALUE,因此通常不会出现线程满的状况。不过会出现资源不够建立不了线程报错,慎用。
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • SingleThreadPool 只有一个线程能执行,其余后入的线程排队。
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • ScheduledThreadPool 见下

ScheduledThreadPool

继承自 ThreadPoolExecutor,增长了定时功能。若是想实现定时运行就考虑一下这个东西。

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

使用的DelayedWorkQueue 队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务

参考

https://blog.csdn.net/jgteng/article/details/54411423 https://blog.csdn.net/z69183787/article/details/80520659

相关文章
相关标签/搜索