java线程池总结

前言

使用线程池的好处

  • 降低资源消耗 降低重复创建和销毁线程的资源消耗。
  • 提高响应速度 任务到达时不需要等待线程创建。
  • 提高线程的可管理性。使用线程池可以对线程池进行统一的分配,调优,和监控。

线程池流程

在这里插入图片描述
在这里插入图片描述

线程池的使用

创建

使用ThreadPoolExecute()

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler){
}
  • corePoolSize:核心线程数
  • maximumPoolSize:线程池最大线程数(最大线程数一般设为2N+1最好)
  • keepAliveTime:工作线程空闲后存活时间。
  • unit:keepAliveTime的单位
  • workQueue:等待队列。(队列类型见下文)
  • threadFactory:用于设置创建线程的工厂
  • handler:饱和策略

阻塞队列类型

  • ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。
  • LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
  • PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

饱和策略

  • AbortPolicy:直接抛出异常

  • CallerRunsPolicy:只用调用者所在线程来运行任务

  • DiscardOldestPolicy:丢弃队列中最旧的一个任务,并执行当前任务。(队列头头的被丢弃)

  • DiscardPolicy:不处理,丢弃掉。(丢掉最新的)

通常而言,这四种拒绝策略我们一般都不太适用我们的业务场景,我们一般都会自定义自己的拒绝策略,将线程任务放进redis或者mq消息队列中。

Executors提供的四种线程池

newFixedThreadPool 创建固定数目线程的线程池。
public static ExecutorService newFixedThreadPool(int nThreads){
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, 
    TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
}
  • FixedThreadPool是一种容量固定的线程池;
  • 阻塞队列采用LinkedBlockingQueue,它是一种无界队列;
  • 由于阻塞队列是一个无界队列,因此永远不可能拒绝执行任务;
  • 由于采用无界队列,实际线程数将永远维持在nThreads,因此maximumPoolSize和keepAliveTime将无效。
newCachedThreadPool 可缓存的线程池
public static ExecutorService newCachedThreadPool(){
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, 
    new SynchronousQueue<Runnable>());
}
  • CachedThreadPool是一种可以无限扩容的线程池;
  • CachedThreadPool比较适合执行时间片比较小的任务;
  • keepAliveTime为60,意味着线程空闲时间超过60s就会被杀死;
  • 阻塞队列采用SynchronousQueue,这种阻塞队列没有存储空间,意味着只要有任务到来,就必须得有一个工作线程来处理,如果当前没有空闲线程,那么就再创建一个新的线程。
newSingleThreadExecutor 单线程化的线程池
public static ExecutorService newSingleThreadExecutor(){
    return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, 
    new LinkedBlockingQueue<Runnable>());
}
  • 只会创建一个工作线程来处理任务。
newScheduledThreadPool
public static ScheduledExecutorService 
newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}

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

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

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;
    }

  • ScheduledThreadPool接收SchduledFutureTask类型的任务,提交任务的方式有2种;
  1. scheduledAtFixedRate;
  2. scheduledWithFixedDelay;
  • SchduledFutureTask接收参数:
    time:任务开始时间
    sequenceNumber:任务序号
    period:任务执行的时间间隔
  • 阻塞队列采用DelayQueue,它是一种无界队列;
  • DelayQueue内部封装了一个PriorityQueue,它会根据time的先后排序,若time相同,则根据sequenceNumber排序;
  • 工作线程执行流程:
  1. 工作线程会从DelayQueue中取出已经到期的任务去执行;
  2. 执行结束后重新设置任务的到期时间,再次放回DelayQueue。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值