【JUC】Executors常用线程池

一、线程池

线程池的好处:

  1. 减少了创建和销毁的次数,每个工作线程都可以重复利用;
  2. 可以根据系统的承受能力设置线程池中的线程数量,防止由于创建过多的线程导致内存占用过大最后死机。

二、Executors提供的常用线程池

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
复制代码
  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:当线程数大于核心时,空闲线程存活时间
  • unit:存活时间单位
  • workQueue:保持任务的队列
  • threadFactory:执行程序创建线程的工厂
  • handler:超出队列而使用的拒绝策略

1、newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务;此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

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

corePoolSize、maximumPoolSize都为1的线程池,无界队列;此线程池一般用于顺序执行任务。

2、newFixedThreadPool

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变。

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

corePoolSize、maximumPoolSize一样,线程数不会超过nThreads,也不会出现空闲线程回收

3、newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全取决于系统能够创建的最大线程大小。

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

无核心线程数,最大线程数为int的最大值,使用SynchronousQueue队列,此队列不存放任务,所以每次有任务过来如果没有空闲线程就会创建新的线程来执行此任务

4、newScheduledThreadPool

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

与其他线程池不一样的是,这里使用的DelayedWorkQueue延迟队列

三、拒绝策略

CallerRunsPolicy:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        r.run();
    }
}
复制代码

AbortPolicy:处理程序遭到拒绝将抛出运行时RejectedExecutionException(默认的拒绝策略)

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    throw new RejectedExecutionException("Task " + r.toString() +
                                         " rejected from " +
                                         e.toString());
}
复制代码

DiscardPolicy:任务将被删除(此拒绝策略什么都不做,将会抛弃此任务)

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
复制代码

DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        e.getQueue().poll();
        e.execute(r);
    }
}
复制代码

猜你喜欢

转载自juejin.im/post/5e9c4179f265da48011769cd