Java线程池实践原理学习(一)

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

因为后面可能涉及到从云端拉去大量的数据到本地,我自己认为应该要用到多线程来加快执行任务的时间,所以我打算在这篇文章中,和大家一起学习线程池的原理,作为技术沉淀。

一、写在前面

1.1 线程的状态

其实我本人对待线程一直是抱着他们是计算机里的小精灵🧚‍♀️来看待的,他们会休息会工作会抢东西,创造他们需要时间,安排他们工作也需要时间,这就是线程的上下文切换。在Java中,线程可以分为5种状态,如下所示:

  1. 新建(NEW):新创建了一个线程对象
  2. 可运行(RUNNABLE) 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu的使用权。
  3. 运行(RUNNING) :可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。
  4. 阻塞(BLOCKED) :阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
* 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
* 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入 **锁池(lock pool)** 中。
* 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
  1. 死亡(DEAD) :线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。

1.2 线程池是什么

线程池(Thread Pool)是一种基于池化思想管理线程的工具,线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。

当然,使用线程池可以带来一系列好处:

  • 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造 成的损耗。
  • 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。

二、线程池核心设计与实现

这节我们将会根据JDK1.8中的ThreadPoolExecute来分析Java线程池的核心设计与实现。

image.png

  • Executor提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注如何创建线程,如何调度线程来执行任务,用户只需提供 Runnable 对象,将任务的运行逻辑提交 到执行器 (Executor) 中,由 Executor 框架完成线程的调配和任务的执行部分。
  • ExecutorService 接口增加了一些能力:
+ 扩充执行任务的能力,补充可以为一个或一批异步任务生成 Future 的方法;
+ 提供了管控线程池的方法,比如停止线程池的运行。
  • AbstractExecutorService 则是上层的抽象类,将执行任务的流程串联了起来,保证下层的实现只需关注一个执行任务的方法即可。
  • ThreadPoolExecutor 实现最复杂的运行部分,ThreadPoolExecutor 将会一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好的结合从而执行并行任务。

下图为线程池中的运行流程:
6A0B7609-FBDE-4121-BC33-6FF4A81446DD.png

我们可以看到线程池内部就像生产者和消费者之间的关系。主要分成了两个部分,分别是任务管理和线程管理,生产者提供任务后,由线程管理者来负责后续的流转。

  • 直接申请线程执行任务
  • 缓冲到队列中等待线程执行
  • 拒绝该任务

在下节内容中,我将和大家一起学习线程池的生命周期管理。

感谢美团技术团队的技术支持。美团技术团队

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%