在线程的相关介绍中,有讲到“线程的实现”分为三种:内核支持,用户级以及两者混合。(这只是一种简要的分类)
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),因为有太多封装好的类,所以很快你就会忘记了,对于深度封装的类,不了解基础又无法深入,所以根本就学不会多线程。
以上纯属一家之言,如果有理解错误的地方,欢迎文明指正。