java线程池详解

池化思想在我们的日常开并不少见,有数据库连接池、线程池、对象池、常量池等等。下面我们主要针对线程池来一步一步揭开线程池的面纱。

  • 使用线程池的好处
  • 1、降低资源消耗
    • 可以重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 2、提高响应速度
    • 当任务到达时,任务可以不需要等到线程创建就能立即执行。
  • 3、提高线程的可管理性
    • 线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控

谈到线程池,我们自然离不开ThreadPoolExecotor类

  • ThreadPoolExecotor
    ThreadPoolExecotor 有许多的构造方法,但所有的构造方法最后都调了下面的最后一个构造函数
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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

居然有7个参数,接下来我们就来一一分析一下参数的作用

 int corePoolSize  // 线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。
 int maximumPoolSize  // 线程数的上限
 long keepAliveTime // 超过corePoolSize的线程的idle时长,超过这个时间,多余的线程会被回收。
 TimeUnit unit //时间单位
 BlockingQueue<Runnable> workQueue  // 任务的排队队列
 ThreadFactory threadFactory  // 新线程的产生方式
 RejectedExecutionHandler handle  // 拒绝策略
  • 线程池的工作顺序
    If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
    If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
    If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.

  • corePoolSize -> 任务队列 -> maximumPoolSize -> 拒绝策略

  • 常用工作队列

    • ArrayBlockingQueue
    • PriorityBlockingQueue
    • LinkedBlockingQueue
    • Synchronous
    • DelayQueue
  • 常用拒绝策略

  - ThreadPoolExecutor.AbortPolicy;//丢弃任务并抛出RejectedExecutionException异常。 
  - ThreadPoolExecutor.DiscardPolicy;//也是丢弃任务,但是不抛出异常。 
  - ThreadPoolExecutor.DiscardOldestPolicy;//丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
  - ThreadPoolExecutor.CallerRunsPolicy;//由调用线程处理该任务 
  • threadFactory:线程工厂,主要用来创建线程;
    • 创建新线程时使用的工厂。如果没有另外说明,则在同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态,等等。如果从 newThread 返回 null 时 ThreadFactory 未能创建线程,则执行程序将继续运行,但不能执行任何任务。
三、Executors

我们可以直接使用 ThreadPoolExecotor 类创建线程池,但官方并不推荐我们怎么做,而是使用 Executors 类提供的几个静态方法来创建线程池,那我们先来分析Executors常用的几个方法。

  • Executors常用方法
    • newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
}
  • newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
  • newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }
  • 线程池的大小
    通常我们线程池设置为cpu个数的倍数

参考文章:
https://www.cnblogs.com/CarpenterLee/p/9558026.html
https://www.cnblogs.com/kuoAT/p/6714762.html
https://blog.csdn.net/fuyuwei2015/article/details/72758179

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林木森^~^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值