栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java线程池原理分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java线程池原理分析

文章目录
    • 1. Java线程池类的组织架构
    • 2. 使用线程池静态工厂Executors创建线程池
    • 3. 核心线程池的内部实现 ⭐
    • 4. 为什么不推荐使用Executors创建线程池?
    • 5. 创建自定义线程池

1. Java线程池类的组织架构
  • Executor 最高级线程调度接口
    • ExecutorService 通用线程池接口
      • AbstractExecutorService
        • ThreadPoolExecutor – 线程池实现类
      • ScheduledExecutorService – 执行周期性任务的线程池实现类(不要用ExecutorService来引用)
      • Executors – 线程池创建的静态工厂类
2. 使用线程池静态工厂Executors创建线程池
  • Executors.newSingleThreadExecutor(); // 创建只有一个线程的线程池

  • Executors.newFixedThreadPool(10); // 创建固定数量线程的线程池

  • Executors.newCachedThreadPool(); // 创建线程数动态调整的线程池,线程缓存时间为60S,最多创建Integer.MAX_VALUE 个线程

  • Executors.newScheduledThreadPool(5); // 创建一个周期性执行任务的线程池,

3. 核心线程池的内部实现 ⭐

​ 查看源代码可以发现Executors 工厂类创建线程池的方法都是对 ThreadPoolExecutor 类的包装。

ThreadPoolExecutor构造函数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

七个核心参数:

  • corePoolSize 核心线程数,即使线程空闲也不会回收
  • maximumPoolSize 最大线程数,线程池中可创建线程的上限
  • keepAliveTime 多余线程的存活时间
  • unit 存活时间的单位
  • workQueue 任务队列,存放被提交后等待执行的任务
  • threadFactory 线程工厂,用于创建线程,一般使用默认的
  • handler 拒绝策略,当太多任务来不及处理要如何拒绝任务

任务队列(BlockingQueue)的具体实现:

  • SynchronousQueue 直接提交的队列:总是将新的任务直接提交给线程执行,如果没有空闲线程则进行创建,如果达到了最大线程数量限制就执行拒绝策略。如果设定了最大线程数为Integer.MAX_VALUE可能会导致创建出大量的线程耗尽系统资源。

  • ArrayBlockingQueue 有界任务队列:若线程池实际线程数小于corePoolSize则会优先创建线程,若大于corePoolSize会将任务提交到队列中进行等待,若队列已满而且线程数小于最大线程数则创建新线程执行,否则执行拒绝策略。

  • linkedBlockingQueue 无界任务队列:除非资源耗尽,否则任务可以一直入队,有造成OOM的可能。

  • PriorityBlockingQueue 优先任务队列:该队列会先执行优先级高的任务。


线程工厂:

可对创建的线程进行定制,一般使用默认即可,

ThreadFactory threadFactory = Executors.defaultThreadFactory();

拒绝策略: 四种

AbortPolicy: 直接抛出异常,阻止系统正常工作(默认拒绝策略)。

CallerRunsPolicy: 交给调用线程(提交任务的线程)来处理该任务。

DiscardOldestPolicy: 丢弃最老的一个任务,并尝试提交当前任务。

DiscardPolicy: 丢弃无法处理的任务,不会抛出任何异常。

4. 为什么不推荐使用Executors创建线程池?
  • 以Executors.newFixedThreadPool(10); 创建固定数量线程的线程池为例,他使用的是无界任务队列linkedBlockingQueue,当过多的任务提交过来又处理不完时任务不断被存放到无界任务队列中会造成队列长度不断增加,最后可能会导致OOM异常。

  • 以newCachedThreadPool(); 创建动态数量线程的线程池为例,他在调用ThreadPoolExecutor创建线程池的时候将最大线程数设置为了Integer的最大值,当过多任务提交过来时可能会导致线程创建过多从而耗费了大量系统资源。

ps:推荐直接使用ThreadPoolExecutor类来直接创建线程池,让开发人员更了解线程池创建的核心参数。

5. 创建自定义线程池
public class CustomThreadPool {
    public static class Task implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        Task task = new Task();
        // 创建自定义线程池
        // 无界任务队列:new linkedBlockingQueue<>(10)
        // 默认线程创建工厂:Executors.defaultThreadFactory(),
        // 使用提供的抛出异常拒绝策略 new ThreadPoolExecutor.AbortPolicy()
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS,
                new linkedBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        // 提交任务到线程池中进行执行
        threadPoolExecutor.submit(task);
        // 任务执行完毕关闭线程池
        threadPoolExecutor.shutdown();
    }

}

待补充:2021年10月23日23:10:14

  • 自定义线程工厂threadFactory
  • 自定义拒绝策略

参考《实战Java高并发程序设计》

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/344952.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号