线程池中的一些细节

线程池的工作原理

我认为线程池它就是一个调度任务的工具。

众所周知在初始化线程池会给定线程池的大小,假设现在我们有 1000 个线程任务需要运行,而线程池的大小为 10,20 个线程来调度这1000个任务。

而这里的 10~20 个线程最后会由线程池封装为 ThreadPoolExecutor.Worker 对象,而这个 Worker 是实现了 Runnable 接口的,所以他自己本身就是一个线程。

深入分析

ExecutorService executorService =  new ThreadPoolExecutor(2,2,0L,TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(2));

这里我们来做一个模拟,创建了一个核心线程、最大线程数、阻塞队列都为2的线程池。

这里假设线程池已经完成了预热,也就是线程池内部已经创建好了两个线程 Worker

当我们往一个线程池丢一个任务会发生什么事呢?

  • 第一步是生产者,也就是任务提供者他执行了一个 execute() 方法,本质上就是往这个内部队列里放了一个任务。
  • 之前已经创建好了的 Worker 线程会执行一个 while 循环 ---> 不停的从这个内部队列里获取任务。(这一步是竞争的关系,都会抢着从队列里获取任务,由这个队列内部实现了线程安全。)
  • 获取得到一个任务后,其实也就是拿到了一个 Runnable 对象(也就是 execute(Runnable task) 这里所提交的任务),接着执行这个 Runnable 的 run() 方法,而不是 start(),这点需要注意后文分析原因。

为什是 run() 而不是 start()

为什么线程池在调度的时候执行的是 Runnable 的 run() 方法,而不是 start() 方法呢?

网上大牛讲的都是只有执行了 start() 方法后操作系统才会给我们创建一个独立的线程来运行,而 run() 方法只是一个普通的方法调用。

而在线程池这个场景中却恰好就是要利用它只是一个普通方法调用。

假设这里是调用的 Runnable 的 start 方法,那会发生什么事情。

如果我们往一个核心、最大线程数为 2 的线程池里丢了 1000 个任务,那么它会额外的创建 1000 个线程,同时每个任务都是异步执行的,一下子就执行完毕了

从而没法做到由这两个 Worker 线程来调度这 1000 个任务,而只有当做一个同步阻塞的 run() 方法调用时才能满足这个要求。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值