线程池

一、线程池好处:

(1)重用线程,避免线程创建和消耗带来的性能消耗
(2)控制线程池的最大并发数,避免线程之间抢系统资源而导致的阻塞现象。
(3)对线程管理,提供定时执行等功能。

二、线程池创建:

1、Executor接口:

public interface Executor {
    void execute(Runnable command);
}复制代码

将任务提交和执行解耦,参数传入Runnable(任务),通过execute方法进行任务执行。

2、ThreadPoolExcutor:

线程池核心实现类:

public class ThreadPoolExecutor extends AbstractExecutorService {复制代码

public abstract class AbstractExecutorService implements ExecutorService {复制代码

public interface ExecutorService extends Executor {复制代码
  • ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
  • 抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
  • 然后ThreadPoolExecutor继承了类AbstractExecutorService;

3、ThreadPoolExcutor 构造和参数

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}复制代码

  • corePoolSize:核心线程数。默认线程池为空,任务提交会创建线程,当前线程数少于corePoolSize会创建新线程,大于或等于corePoolSize则不创建。
  • maximumPoolSize:最大线程数。如果任务队列满了,线程数小于maximumPoolSize,线程池会创建新线程处理任务。
  • keepAliveTime:非核心线程闲置的超时时间。非核心线程,如果没任务可执行,超过时间后会被回收。设置allowCoreThreadTimeOut属性为true,keepAliveTime也作用于核心线程。
  • unit:keepAliveTime时间参数,天、小时、分钟、秒、毫秒等。
  • workQueue:任务队列。当前线程数大于corePoolSize,新任务会被添加到任务队列,队列为BlockingQueue(阻塞队列)。
    • ArrayBlockingQueue:数组组成的有界阻塞队列
    • LinkedBlockingQueue:链表组成的有界阻塞队列
    • PriorityBlockingQueue:优先级排序的无界阻塞队列
    • DelayQueue:用优先级队列实现的无界阻塞队列
    • SynchronousQueue:不存储元素的阻塞队列
    • LinkedTransferQueue:链表组成的无界阻塞队列
    • LinkedBlockingDeque:链表组成的双向阻塞队列
  • threadFactory:线程工厂。可用线程工厂给创建的线程设置名字。
  • handler:饱和策略。线程和队列都满了采用的策略。默认abordPolicy,无法处理新任务,并抛出RejectedExecutionException异常。还有其他三种策略:
    • CallerRunsPolicy:由调用者所在线程处理该任务
    • DiscardPolicy:丢弃该任务,不抛异常
    • DiacardOldestPolicy:丢弃队列最近的任务,重新尝试执行该任务

4、线程池处理流程:


三、线程池种类:

Executors类提供了创建常见线程的方法,主要有四种,FixedThreadPool、CachedThreadPool、SingleThreadExecutor和ScheduledThreadPool。


1、FixedThreadPool

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

可以指定核心线程数和最大线程数。也就是说只有核心线程数,并且线程不会被销毁。任务队列采用的是LinkedBlockingQueue无界阻塞队列。

流程图:


(1)执行execute提交任务,如线程数小于核心线程数,则创建核心线程并执行任务。否则加入阻塞队列。

(2)核心线程如果执行完当前任务,会在队列中取任务并执行。

2、CachedThreadPool

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

核心线程数为0,最大线程数为Integer.MAX_VALUE,空闲线程等待时长位60秒。使用的阻塞队列为SynchronousQueue,该队列不存储元素,每个插入操作必须等另一个线程的移除操作,每个移除操作必须等待另一个线程的插入操作。

适用于少量的几个任务的场景。

流程图:


(1)执行execute提交任务,插入SynchronousQueue队列,同时判断是否有空闲线程,如有则将任务交给空闲线程去取任务处理;如果没有,则创建非核心线程去处理任务(从队列移除)。如果超过60秒无任务,空闲线程会被回收。

适用于大量任务,并且耗时不多的场景。

3、SingleThreadExecutor

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

只有一个核心线程的线程池。采用的阻塞队列为LinkedBlockingQueue。

流程图:


(1)执行execute提交任务,如无核心线程,创建一个核心线程执行任务;如有线程在运行,则将任务加入到队列,等核心线程处理完当前任务,再从队列中取任务处理。

适用于多任务有序进行的场景。

4、ScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}复制代码

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

固定的核心线程数,最大线程数为Integer.MAX_VALUE,队列为DelayedWorkQueue可延时获取数据的无界阻塞队列,所以不会创建非核心线程。

返回了ScheduledThreadPoolExecutor对象,主要用来执行延时任务或定期任务。

流程图:


(1)执行scheduleAtFixedRate或scheduleWithFxiedDelay方法,执行周期性任务或者延时任务时,将任务添加到队列中。并且检查是否达到了核心线程数,没达到就创建核心线程。

(2)DelayedWorkQueue将任务进行排序,核心线程会在队列中取到任务的包装类ScheduledFutureTask,然后去执行任务。

适用于执行周期任务或延时任务。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值