本篇目录
- 你真的理解并发吗? 为什么要应用并发?
- 多线程和并发
- 多线程和多过程
- 多线程肯定快吗
- 学习并发的四个阶段
一、你真的理解并发吗?为什么要应用并发?
咱们有没有见过并发的场景呢?
其实并发是无处不在的,比方,淘宝的双十一就是一个十分高的并发量,就是很多人同时去拜访一个网站,而这个网站却可能撑持大量的并发拜访,这就是一个并发的场景.
粗疏的说,web 容器、数据库服务器,等等各类的服务器软件,都是反对并发的,那么并发的性能就间接的影响到软件的性能
所以并发编程在整个并发利用的场景下是十分要害的,除了咱们刚刚说的各种服务利用之外,那么还有没有其余的中央用到并发呢?
其实也是十分多的刚刚说的是服务端那, 咱们说个客户端 eclipse 就是一个客户端利用它也有大量的并发场景
比如说咱们在编辑代码的时候,它能够做很多的事件: 能够同时运行一个 web 服务、它还在进行编译、甚至能够说底层的垃圾回收等等
也就是说,并发场景在咱们的生存中是无时无刻不在产生的,
那么并发有哪些长处呢?当初硬件越来越便宜,那么咱们就能够通过减少硬件的形式,来进步一个性能。
比如说能够应用多核 CPU,应用并发能够施展出多核处理器的弱小的能力,当然了也不仅仅是多核,咱们能够间接说多处理器,可能施展多个处理器的弱小的运算能力,除了施展多核处理器的弱小能力之外,可能让咱们的建模更加的简略,就是所谓的建模的简略性。
所以咱们要学习并发编程。
二、多线程和并发
多线程和并发之间到底有什么关联呢?它们之间又有哪些差别呢?咱们就来探讨一下。
首先说一下什么是多线程,其实之前曾经给大家讲了一个非常简单的例子了
如果这是咱们的一个利用,如果咱们在这外面写代码
咱们晓得,程序是一行一行的往下执行的,在 Java 虚拟机运行时内存区域中,有一块叫做 PC 寄存器,相似于代码编辑器中的 linenumber,批示的是行号,Java 虚拟机就跟着行号一行一行的往下执行。
必定不会说从执行完 int a = 10; 之后,接着先执行 int c = a + b; 而后再回过头去执行 int b = 20; 这是相对不可能的,这就是单个线程在执行。
就是说,这外面的代码是一行一行的往上来执行的,不会乱序去执行,
咱们晓得在运行一个非常复杂的代码的过程中,Java 的内存治理,咱们并不需要手动的去治理内存,Java 提供了主动内存管理机制,内存的申请和开释都是由 Java 虚拟机来本人实现的。
那么,在进行垃圾回收的过程中,就须要调用垃圾收集器(GC),那么你这个程序在运行的过程中,垃圾收集器也是在工作的。
咱们发现咱们并不知道垃圾收集器在工作,然而垃圾收集器却是曾经在工作了,怎么回事呢?
其实有另外一个线程在执行垃圾收集器,就是专门的垃圾收集器线程,它外面也有一行一行的垃圾收集代码
那么,在咱们程序运行的过程中,这些代码会主动的悄悄的往上来执行。
Java 虚拟机中的内存区域,次要分为两大区域,一个是线程共享区,一个是线程独占区,咱们晓得,堆和办法区是被线程所共享的区域,就是所有的线程共享这块区域,除了这两块区域以外,还有程序计数器
这块区域是被线程所独享的,也就是说每个线程都有这么一块区域,因而,这两个各自都有各自的程序计数器
这两个之间是互不烦扰的,也就是相当于有两段代码在同时的进行,这就是多线程
而后咱们接着说并发的问题,多线程和并发到底有什么关系呢?
并发就是并行的执行,是不是跟多线程十分的相似呀,那么多线程是不是就是并发呢?
其实不是,从狭义上来说,咱们可能就认为多线程就是并发,然而,实际上多线程不是并发,咱们能够这么去想。
咱们晓得源码会被编译成字节码,而咱们 Java 虚拟机执行的就是字节码指令,那么它在最终执行过程中是由 CPU 执行的
假如有一个一个炉子用来考烧饼的,这些是炉子下面放的烧饼
这个炉子的上面,有一个火炉
如果当火转到对应的这个火炉下面的烧饼才开始烤,假如这个烧饼是咱们的线程,而上面的这个火炉是咱们的 CPU
当炉子在转的十分快的时候,咱们说,工作的 切换 即线程之间的 切换工夫 就会十分的短,那么咱们就会看起来像是在同时执行,然而其实并不是在同时执行,它是在不停的切换的,就相似于图片切换的频率十分高的时候就成了动画或成了视频
这个原理其实也相似于咱们的灯泡,灯泡其实也是在不停的闪的,咱们看到灯泡始终亮,就是因为它闪的频率十分的高,这就是多线程。
多线程其实 并不是多个线程一起执行 , 而是线程之间因为 切换的速度十分的快,所以,咱们看起来像不间断的执行
那么,并行又是什么呢?并行就不一样了,并行 示意的是多个工作同时执行
就是说,这么多的烧饼在一块烤,那怎么做到的?有多个炉子就能够做到了。每个烧饼上面有一个炉子,这样就能做到一块烤了,这就是所谓的并行。
那么,并发和多线程之间其实通过这个例子就可以看的十分分明了,多线程并不一定是并发,如果是并发执行,那么必定是多个线程在一块执行,当然也未必,多个过程也是并发执行。
这就是多线程和并发之间的关系。
三、多线程和多过程的关系
什么是过程?简略来讲就是运行中的程序,那么何为运行中的程序呢?咱们如何来看看过程呢?
操作系统都是多过程的。咱们通过工作管理器就能够看到操作系统中以后运行的很多的过程
过程和线程之间到底有什么关联呢?
首先过程是资源分配的根本单位,第二个过程中蕴含多个线程,线程能够共享过程的资源。
咱们能够这么了解,就是说过程是操作系统级别的,一个操作系统运行了多个过程,每一个过程外面有蕴含着多个线程,咱们能够通过下图这个中央来看
这外面有一个 CPU 的统计信息,此处有一个过程数是 137,就是运行了 137 个过程,线程有 1720 个
显然线程的数量远远大于过程的数量,也就是说,一个过程外面会有多个线程。
咱们的 eclipse 软件就是一个过程,咱们看一个过程中到底蕴含了多少个线程呢?咱们之前也通过 jconsole 监控工具
为什么处理器调度的根本单位是线程而不是过程?咱们说,过程是资源分配的根本单位,在进行过程之间的切换的过程中,它会节约更多的资源,然而线程能够说是轻量级的过程,所以 CPU 的调度的根本单位是线程
这就是线程和过程之间的分割与区别
四、多线程肯定块吗?
多线程执行肯定会快吗?
咱们大家可能都晓得在很多的下载的网站上,都会提多线程下载,那么咱们也同样的发现,应用多线程下载远比单线程下载要快的多。这样可能大家都会认为多线程肯定比单线程快,其实并不一定
咱们来举个例子,还是拿之前烤烧饼的例子来说,上面只有一个炉火,下面在不停的转,这样烤肯定会快吗?
咱大家想一下如果咱们不这样做,咱们不让它转,就让它烤这一个,等它烤熟了之后,咱们再拿另外一个烤
那么咱们想一下,是之前的全副放上去让炉子转起来烤,烤的快呢?还是我一个一个放上去烤,烤的快呢?
其实是非常明显的,如果选在转的话,在转的过程中,每个烧饼(线程)切换的过程中是有空隙的
线程工作之间在进行切换,也就是说,烧饼在进行切换的过程中,它是要节约咱们的资源的,也就是要节约咱们的能量的,因而,其实是远远不如一个一个的执行反而更快一些
回过头咱们再来解释方才提到的对于迅雷下载,就是说多线程下载的问题,多线程下载为什么肯定可能进步,也并非肯定可能进步下载的速度?
按理绝大部分状况下是能够的,为什么呢?因为,咱们说做一个文件服务器的话,容许用户去下载那么,它必定不会说你这个链接过去了,我就会毫无保留的一下子把我的带宽全副给你让你去下载
我必定是为每一个链接调配肯定的带宽,比如说,你这一个连贯进来,我就给你这个响应最高 200k 不能再多了,那么也就是说你这一个链接进来,它的峰值下载速度也就是 200k,那么它是一个链接级别的。
那么,我能够把要下载的一个文件分成多个,切分成多个,我用多个线程一块去下载,那么,每一个链接 200k,假如有三个链接,那么,加起来就是一共有 600k 的下载速度。
那么等我把切分的每一小块文件都下载完了之后,我在把这些小文件合并起来就能够了,这样下载的速度就会变的很快,也就是说多线程下载并不是多线程进步了速度,不是多线程的性能进步了。
而是因为内部服务器对资源的限度,所导致的一个问题那么多个链接就冲破了这个近程服务器的限度,也就导致了性能的进步。
也就是说,尽管看着下载速度快了,并不是多线程的性能进步了,而是因为近程服务器的问题
五、学习并发的四个阶段
第一阶段:相熟把握 API,可能实现并发编程
熟练掌握 并发相干的 API,可能实现根本的并发编程
也就是咱们所相熟的继承 Thread 也好,实现 Rannable 接口也好,应用各种的锁,根号中期,注册队列等等
你要熟练掌握这些和并发相干的 API,这是第一个阶,这个阶段指标是:how(怎么做)
第二阶段:熟读 API 源码,把握原理
咱们会用这些 API 还不行,咱们要把握 这些 API 实现的原理,理解了这些原理之后对咱们来说
无论是深刻了解并发也好或者说当前咱们的编程也好都是有十分大的帮忙的,这个阶段的指标是:what(what)
第三阶段:了解 Java 虚拟机的内存模型
Java 的运行是基于 JVM 的,那么JVM** 是如何解读多线程的呢?如何解读咱们的并发代码呢?
** 这就须要咱们深刻了解 Java 虚拟机的内存模型,以及 Java 虚拟机执行多线程的执行引擎等等
就是对于虚拟机相干的对线程的一些反对,这就深刻到了 Java 虚拟机的档次,这就是第三个阶段
第四阶段:操作系统对并发的反对
Java 虚拟机是运行在 操作系统 上的,第四个阶段就是操作系统对并发的反对有哪些
参考资料
龙果学院:并发编程原理与实战(叶子猿老师)