Java 线程池学习

- 为什么要有线程池?
为了避免系统频繁的创建和销毁线程,可以让创建的 线程进行复用。

- JDK 中 线程池类的关系
在这里插入图片描述
- ThreadPoolExecutor 以及线程池工作原理分析
1.ThreadPoolExecutor 参数说明:
在这里插入图片描述
关于 WorkQueue 的详细说明上一篇BlockingQueue
拒绝策略handler 的说明:
在这里插入图片描述

2.线程池工作原理源码分析:
1.1 submit 源码分析在这里插入图片描述
源码的 submit 中有三个分支:

  1. 如果 工作线程数 < corePoolSize,调用addWorker(command, true);
  2. 如果 工作线程数 > corePoolSize,且 当前线程池是running 状态, 将当前任务加入到 workQueue 中。
  3. 如果 加入工作线程失败(队列已满),执行addWorker(command,false), 其实是新创建线程执行该任务。

1.2 addWorker 源码分析:

boolean addWorker(Runnable firstTask, boolean core) 
core: 为true 表示将该线程绑定到corePoolSize, 如果为true 表示将该线程绑定到 maxiNumPoolSize

在这里插入图片描述
1.addWorker 对 传入的任务firstTask 进行了封装,通过Worker 来封装.可以查看 Worker 的构造函数, 有成员变量thread, 这个是通过 参数ThreadFactory 来创建的线程。

  Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

2.最终调用 worker.thread.start 来执行 任务, 最终会调用Worker.runWorker.
runWorker 会 执行任务的task.run()。
1.3 runWorker 分析:
在这里插入图片描述

  • task 的取值有两种: 从参数中传过来的,或者通过getTask 获取的。 getTask 即 从blockingQueue 中take出来的. 这就实现了循环利用线程。

  • Executors 工程类提供的不同特性的线程池:

    1. newFixedThreadPool: 存在的问题是 这里 使用的是无界队列,存在一个问题, 如果 并发量比较大, 很有可能 无界队列中很多未处理的任务,最终内存耗尽。
      在这里插入图片描述
      在这里插入图片描述
  • newSingleThreadPool:
    在这里插入图片描述
    在这里插入图片描述
    3.newCachedThreadPool 如果有大量任务提交,任务执行又没那么快,就有等量的 线程被创建。很快会耗尽系统资源
    在这里插入图片描述
    在这里插入图片描述

- 自定义线程池
JDK 提供的线程池都存在一些问题, 在线上不建议使用。
线程池的线程大小估计:
在这里插入图片描述

参考

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值