Java线程池

为什么要用线程池

  • 降低频繁创建销毁线程带来的性能损耗,以达到线程重复利用
  • 提高线程的可管理性

ThreadPoolExecutor参数详解

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)                         
  • corePoolSize 核心线程数。创建后会有这么多条核心线程,核心线程即使空闲下来也不会销毁;

  • maximumPoolSize 最大线程数

  • keepAliveTime 线程空闲的存活时间。线程如果空闲超过keepAliveTime,且是非核心线程,会销毁线程;

  • unit 存活时间keepAliveTime的单位

  • workQueue 阻塞队列

    • ArrayBlockingQueue 数组阻塞队列。根据FIFO排序,属有界队列。
    • LinkedBlockingQueue 链表阻塞队列。根据FIFO排序,默认容量为Integer.MAX_VALUE,可指定大小,吞吐量比ArrayBlockingQueue 高。
    • SynchronousQueue 同步队列。向该队列放入一个任务,必须要有空闲线程去取走一个任务才可放入,如果没有空闲线程取走就创建新线程,创建不了就执行拒绝策略。
    • PriorityBlockingQueue 带优先级的无界阻塞队列。
  • threadFactory 创建线程的工厂,可用于设置线程的名称

  • handler 拒绝策略。当workQueue队列满了,且线程数已经达到最大,新来的任务会由该策略进行处理;
    线程池提供了4种策略:

    • AbortPolicy 抛出异常
    • CallerRunsPolicy 由调用者当前线程执行
    • DiscardPolicy 丢弃任务
    • DiscardOldestPolicy 丢弃最早的任务
      此外,我们还可以通过实现RejectedExecutionHandler接口,自定义拒绝策略。

ThreadPoolExecutor原理

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    else if (!addWorker(command, false))
        reject(command);
}
  1. 线程池创建后,当任务提交到线程池时:
  2. 当线程数 <= corePoolSize ,会先用核心线程来执行任务,否则任务会放进workQueue队列中;
  3. 当workQueue也放满任务,且maximumPoolSize>corePoolSize,会创建新的线程执行任务;
  4. 当线程数达到maximumPoolSize,且workQueue也放满任务,新来的任务会由RejectedExecutionHandler处理;
  5. 当非核心线程空闲(指空闲keepAliveTime这么长时间)后,会销毁线程;

为什么阿里推荐自定义线程池

Executors提供的线程池各有优劣,自定义一个统一的线程池可以减少线程池的滥用问题,方便排除监控

Executors提供的5种线程池

newFixedThreadPool

固定线程数线程池,这种线程池的核心线程数和最大线程数都是一样的,阻塞队列用的是LinkedBlockingQueue,由于是无界队列,所以当任务数过大时,阻塞队列可能发生OOM

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

newSingleThreadExecutor

单线程线程池,可见和newFixedThreadPool大体一样,只是核心线程数和最大线程数都是1,其他都一样。

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

newCachedThreadPool

可缓存线程池,这种线程池使用要注意最大线程数为Integer.MAX_VALUE,有可能发生因为创建太多的线程而OOM。

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

newScheduledThreadPool

定长线程池,支持延迟或周期性任务。最大线程数是Integer.MAX_VALUE,且使用DelayedWorkQueue延迟队列,同时也是无界队列,任务过多也有可能导致OOM。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

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

newSingleThreadScheduledExecutor

原理和newScheduledThreadPool一样

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值