在线程的相关介绍中, 有讲到 "线程的实现" 分为三种: 内核支持, 用户级以及两者混合.(这只是一种简要的分类)
Java 线程在 JDK1.2 之前, 是用户线程实现的
而在 JDK1.2 中, 线程模型变为基于操作系统原生线程模型来实现的
所以说 Java 虚拟机中线程的映射实现, 是受制于操作系统的, 操作系统支持怎样的线程模型, 决定了 Java 虚拟机中线程的样子.
虚拟机规范中也并未限定 Java 线程需要使用哪种线程模型来实现.
线程模型只对线程的并发规模和操作成本产生影响, 对 Java 程序的编码和运行过程来说, 这些差异都是透明的.
目前因为 Windows 和 Linux 系统提供的线程模型就是一对一的, 所以对于 Sun JDK 来说, 它的 Windows 版与 Linux 版都是使用一对一的线程模型实现的, 一条 Java 线程就映射到一条轻量级进程之中
简言之, 现在的 JDK 线程模型基于操作系统原生线程, 所以模型依赖于操作系统对线程的支持, 另外 Windows 和 Linux 系统提供的线程模型就是一对一的
所以可以简单认为:
现在 Java 线程与操作系统线程一对一映射
现在的 Java 线程, 就是操作系统中的线程
至于 JVM 将 Java 线程与操作系统的线程是如何映射的? 不同的操作系统中具体的线程是如何实现的? 是另外的两个很深的问题.
之所以提到 Java 线程与操作系统线程, 其实是想说, 操作系统中将程序的运行抽象为进程和线程, 有一套抽象的理论体系, 其实 Java 线程与他们是同根同源的, 核心思维逻辑是相同的, 所以前面简单了解到的操作系统对于进程, 线程的相关内容, 并不是那么的废话.....~□~||
不过尽管相似之处太多太多, 虽同根同源, 但是却又千差万别, 每个人从生物的角度来说, 骨骼多少块? 肌肉多少块? 几只眼睛? 几只耳朵?.. 尽管这都是相同的, 但是每个人真的一样么, 脾气? 秉性? 能力?...
一切都是 Thread
Thread 是 Java 对线程的抽象描述, 所以多线程编程模型必然是针对 Thread
不管 JVM 与操作系统的线程到底如何映射, 到底如何运行, 面对 Java, 程序员看到的就只是 Thread
代码中操作的这个 Thread 类的实例, 就好比是操作系统底层线程的一个指针(句柄), 你想这个线程怎么样, 通过操作这个 Thread 实例对象即可
抛开之前篇章中关于操作系统, 进程, 线程, 同步, 控制, 死锁等底层基础知识的介绍, 从 Java 多线程编程的视角看, 我们就是在操纵不同的 Thread 对象实例, 对这些实例进行不同的配置, 并且让他们相互协作.
Thread 是一个类, 用于描述了线程这一概念, Thread 有自身的属性信息比如名称, 这些属性信息用于描述线程本身或者用于支撑线程可以操作的行为.
如同我们定义一个 Person 类, 这个类拥有一些属性和方法, 然后定义了一些实例对象进行协作.
多线程开发就是操纵 Thread 对象
Java 多线程程序开发中, 程序员创建 Thread 类的实例, 并且对实例进行配置, 然后通过可操作的行为方法对他们进行管理调度, 使程序以多线程的形式运行
在神话故事中, 女娲娘娘抟土造人, 每一个人都是 "人类" 的一个实例, 每个人有姓名性别等属性信息,"人类" 有自身的能力(行走, 说话, 思考, 认知等), 通过后天的努力学习也都有各自的能力(线程任务), 整个世界由一个个不同的人, 整个社会的活动由所有的人的相互的行为交互构成.
对于 Java 多线程程序开发中的程序员们来说, 不就相当于神话故事中的女娲娘娘么
整个多线程的世界里面, 都是 Thread 的实例对象, 程序员负责创建, 配置, 管理调度这些对象, 也就形成了支持多线程的程序了.
尽管多线程编程非常繁琐, 复杂, 易错, 但是如果理解清楚了 Thread 的抽象模型, 并且对多线程编程模型中的解决思路熟悉, 就能够编写出来良好的多线程程序.
Thread 的抽象模型往简单了说就是 Thread 这个类, 他有属性字段, 有 public 方法, 也有封装到线程任务(Runnable), 对于一个 Thread 的设置, 他就那些可配置项目, 不多不少
所以只要你理解了 Thread 的的抽象模型, 那么你就能够很清晰的对你需要的 Thread 进行配置.
而多线程编程模型中的解决思路就如同下棋时的套路那般, 可以让你更好更快更全面的写出来多线程应用程序.
所以说, 什么是 Java 多线程编程?
只有两个步骤, 创建 Thread 对象, 使用 Thread 对象, 看起来似乎是超乎寻常的简单
使用电脑也很简单, 按下电源键开机, 使用鼠标和键盘, 说起来也是非常的简单, 但是使用计算机完成工作任务, 却不是一件轻松的事情.
多线程不巧的是, 也是如此, 首先多线程编程模型的概念源于操作系统中的多线程(进程), 然后有千差万别, 所以对于 Thread 抽象模型的理解本身就具有一定的门槛
另外, 对于线程的操作有多种方法, 既然是多线程就不止一个线程, 那么多线程, 多交互方法, 必然产生很多种复杂的协作逻辑, 如何能够正确高效的组织, 也是非常考验智商的.
Java 线程逻辑
操作系统中我们对进程进行了介绍, 对于进程作为操作系统对于程序运行的抽象, 核心为进程控制, 进程同步, 进程通信
我们前面有说到 Java 多线程与操作系统中的线程 (进程) 同根同源, 其实 Java 的多线程编程模型核心也是这三部分
对于 Thread 类本身, 拥有其自身的属性, 比如名字, Id, 优先级, 状态等, 这就是进程的控制信息;
对于 Thread 中封装的任务, Java 提供了 synchronized,volatile 关键字用于控制共享资源的访问, 这就是进程的同步;
对于 Thread 中的一些行为(以及从 Object 继承而来的), 比如 join,wait 则相当于进程的通信;
简言之, Java 中对操作系统中的进程的控制, 同步, 通信, 都有抽象, 当然对于 Java 线程来说, 从编程的角度看, 他的主宰不是操作系统而是我们程序员.
所以说绕来绕去, 即使我们说的是 Java 中的多线程, 还是绕不开 "控制, 同步, 通信" 的概念.
Java 多线程编程到底是什么
所以说了这么多, 到底 Java 多线程编程到底是什么? 我们前面说只有两个步骤 "创建 Thread 对象, 使用 Thread 对象"
这两个部分是对线程本身的控制与处理, 但是在使用 Thread 对象时, 还有一个最重要的部分, 也就是为什么我们要使用线程?
还不是为了执行任务?
所以说, 任务的执行也是非常重要的代码, 因为, 多线程中的代码不再是简简单单的完成任务那么简单, 因为如果涉及到共享资源的访问, 所以就是涉及到进程同步的问题.
所以想要学习 Java 多线程, 第一个部分, 理解清楚 Java 对线程概念的抽象以及 Thread 支持的控制操作方法 --- 也就是 Thread 类本身.
第二个部分, 理解清楚 Java 中同步的逻辑, 也就是同步关键字的透彻理解.
第三个部分, 理解清楚 Java 对于线程通信的抽象, 也就是相关方法比如 wait 的逻辑
以上三个部分就是 Java 多线程的基础, 如果真的彻底理解了, 我相信任何人都可以写出正确的多线程代码.
但是, 谁会非要从炼钢开始造汽车? 电脑城中组装电脑的店铺一大把, 谁会自己组装一个 CPU 或者风扇?
发展到如今, Java 也提供了更多的 "工具类", 也不断有一些好的设计模式与理念产生, 所以, 想要真的成为大师, 你还要学会用好各种工具, 站在前人的肩膀上.
所以, 多线程编程的学习如上内容.
在上篇中, 对操作系统中关于进程线程的相关概念进行了简单介绍, 以有助于下一步能够快速理解 Thread 抽象模型
在中篇中, 将会详细介绍 Java 的多线程编程基础.
在下篇中将会对多线程编程中的经典模式, 工具类进行简单介绍.
总结
Java 线程与操作系统线程的概念是同根同源的, 根本逻辑是一致的, 如同你跟另外一个人, 生物上看都是 "人类", 尽管从另外的很多角度你们是千差万别的.
操作系统是为了多程序 (任务) 的并发运行, 所以有了进程抽象概念, 为了程序内部更好的并发运行 , 所以有了线程的概念.
他们都是围绕着并发, 提高处理机利用率等目的, 他们面对的问题也都是相似的, 控制, 同步, 通信.
所以 Java 线程也不例外, Java 线程与操作系统关于并发程序进程的相关概念与解决思路也是相通的
所以 Java 线程对操作系统中的概念进行了抽象, 通过 Thread 类提供的属性和方法, 通过关键字, 通过 Object 的通信方法, 完成了对进程概念的完整描述.
所以, 回头再看操作系统中关于控制, 同步, 通信的内容, 你又会觉得非常有帮助.
多线程的学习很复杂, 如果只是知识点的学习记忆, 其实毫无用处, 因为首先你不会如此深入底层原语(比如直接使用 wait), 因为有太多封装好的类, 所以很快你就会忘记了, 对于深度封装的类, 不了解基础又无法深入, 所以根本就学不会多线程.
以上纯属一家之言, 如果有理解错误的地方, 欢迎文明指正.
来源: https://www.cnblogs.com/noteless/p/10354673.html