目录
什么是线程、进程
操作系统、进程、线程的包含关系
操作系统是包含多个进程的容器,而每个进程又都是容纳多个线程的容器
什么是进程:
英文是Process,指的是程序的一次执行,在用户下达运行程序的命令后,就会产生进程。
进程是程序(这里可以理解为我们写的代码)的真正运行实例,是资源分配的基本单位。
什么是线程
线程是CPU的基本调度单位,每个线程执行的都是进程代码的某个片段
进程和线程的关系和区别
1)起源不同
先有进程,后有线程。
2)概念不同
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,
进程是系统进行资源分配和调度的一个独立单位;
线程是CPU调度单位
3)内存共享方式不同
默认情况下,内存无法与其他进程共享
线程可以共享由操作系统分配给其父进程的相同内存块
4)拥有资源不同
进程拥有独立内存,而线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
线程共享的内容
1.进程代码段
2.进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)
3.进程打开的文件描述符
4.信号的处理器
5.进程的当前目录
6.进程用户ID与进程组ID
线程独有的内容
1.线程ID
2.寄存器组的值
3.线程的堆栈
4.错误返回码
5.线程的信号屏蔽码
5)数量不同
一个程序至少有一个进程,一个进程至少有一个线程
6)开销不同
线程的创建、终止时间比进程短
同一进程内的线程切换时间比进程切换短
同一进程的各个线程间共享内存和文件资源,可以不通过内核进行通信
相同点
就绪、等待、运行等状态
Java和多线程的关系
Java天生支持多线程、语言排名高
Java线程会一对一映射到操作系统
JVM自动启动线程
线程信息
Signal Dispatcher // 负责把操作系统发来的信号分发给适当的处理程序
Finalizer // 负责对象的finalize()方法,目前不推荐使用
Reference Handler // 和GC、引用相关的线程
main // 主线程,用户程序的入口
什么是多线程
多线程是指在单个进程中运行多个线程。如果一个程序允许允许两个或以上的线程,那么它就是多线程程序。
火锅的比喻
大火锅一个人吃,就是单进程单线程
大火锅多人吃,就是单进程多线程
分开吃小火锅,就是多进程多线程
我吃火锅,别人吃火锅底料,那就是我拥有锁,别人拿不到锁
为什么要用多线程
1)最主要的目的就是提高CPU利用率
1.提高处理速度
2.避免无效等待(IO的时候可以做别的事)
3.提高用户体验:避免卡顿、缩短等待时间
并行处理,提高性能,通常是服务器领域(例如Tomcat),用多个线程去接收进来的HTTP请求,而不是排队等待单一的线程处理
在Android开发中,主线程的重要任务之一是绘制屏幕界面,该线程中不允许进行IO操作或网络请求,目的就是避免卡顿,影响用户的交互
2)便于编程建模
把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。
3)计算机性能定律:摩尔定律失效,阿姆达尔定律登上舞台
摩尔定律:
当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。
阿姆达尔定律:
一般情况下,处理器越多,程序执行的速度就会越快,但是会有一个上限,上限取决于程序中串行部分的比例,并行的比例越高,多处理器的效果越明显。
什么场景中会用到多线程?
1)什么时候需要新开线程
通常在需要进行耗时任务的时候,例如执行磁盘IO读写,或者从网络获取信息的时候。
2)为了同时做多件不同的事
开网页同时听音乐、后台线程比如执行定时任务quartz
3)为了提高工作效率、处理能力
tomcat:每次有一个新的请求过来的时候,tomcat会把这个请求交给一个新的线程去处理,。
多线程后台并行下载文件
NIO和AIO
4)需要同时有很大并发量的时候
压测,如在双十一之前测试服务器承受压力的能力
多线程的局限
1)上下文切换带来的消耗
2)异构化任务(任务结构不一样)很难高效并行
3)带来线程安全问题:包括数据安全问题(例如i++总数不一致)以及线程带来的活跃性问题(线程饥饿、死锁)
串行、并行、并发
串行和并行
串行是大家排队一个个来,并行是大家一起来
并发和并行
单核处理器都可以做到并发,并且是逻辑上的同时运行,处理器切换速度太快以至于感受不到;
多核处理器都在真正同时执行任务,是物理上的同时运行。
并行的概念
真正的同时运行,在同一时刻,有多个任务同时执行。
例如在多核处理器上,有两个线程同时执行同一段代码
可见,单核处理器是无法实现并行的,因为其无法在同一时刻执行多个任务。
并发通常指的是以下两种概念
1)形容多个任务的执行状态
两个或多个任务可以在重叠时间段内启动,运行和完成
并行(两个线程同时执行)一定是并发,并发不一定是并行
2)对“并发性”的简称
程序的不同部分具有可以同时执行的性质
“并发性”是一种程序的性质。如果一个程序具有并发性,说明这个程序的不同的部分可以无序或同时执行,且不影响最终的执行结果。
一个单核CPU例子:
程序具备并发性,但不并行执行:单核并行程序
程序具备并发性,且并行执行:多核
既不并行执行,也不具备并发性:单核串行
并行执行,但程序不具备并发性:不可能
是什么让并发和并行成为可能
操作系统升级
多核CPU
编程语言升级
高并发
什么是高并发?
通常认为是同时有很多个请求发送给服务器系统,服务器并行处理。如双十一、春晚。
高并发和多线程的联系和不同?
高并发可认为是一种状态,指的是大量的请求同时到达服务器所带来的一种结果,结果就是服务器需要同时去处理很多的请求,所以系统需要应对高并发所带来的一种后果。如果处理不当可能会出现响应速度慢,无响应,甚至服务器死机。
多线程是一种编程方式,它是一种解决方案,它是防止高并发所带来的那些线程安全问题或者是性能问题。多线程还有一个目的,就是提高硬件的利用率,如Tomcat为了同时处理多个请求,内部采用了多线程模型,恰恰是为了解决高并发所带来的问题。
高并发并不意味着是多线程:Redis。Redis底层就是用单线程来处理的,并且吞吐量也相当大,峰值可达几十万。
高并发有哪些指标
QPS:每秒请求数
带宽:峰值流量和页面的平均大小
PV:页面浏览量
UV:独立访问
吞吐率(Requests per second)
并发连接数(The number of concurrent connections)
服务器平均请求等待时间(Time per request: across all concurrent requests)
同步与异步
被调用者是否主动告诉调用者结果。
同步
同步指的是,客户端发出一个请求后,在没有得到结果之前,服务端就不返回任何结果。但是一旦服务端返回,那返回的就是客户端想要的结果(而不是告诉客户端再等等之类的内容)。
被调用者主动告诉调用者结果
被调用者(也就是服务器)的行为,而不是请求方的行为。
异步
不实时处理
调用在发出之后,服务端会立刻返回,告诉调用方“我收到你的请求了,我会处理的”
调用发出后,等服务端计算完毕后,服务端会通过发消息等途径来通知调用者,或通过回调函数处理这个调用。
一个买书的例子:
小明想买一本高并发的书,打电话给书店老板,此时有两种情况:一种是老板说:“好,你别挂电话,我去找。”小明在电话一端听老板翻箱倒柜的声音,是不是问老板有没有找到。一直持续到老板给出答复有还是没有。另外一种是老板说:“好,我找找看,你先挂电话吧,我一小时后打给你,告诉你有还是没有。”
这个例子中第一种为同步,第二种为异步。
阻塞和非阻塞
我是调用者,我调用一个东西的后,结果返回前,是否还能做别的事
站在线程状态的角度
站在线程发出请求(通常是HTTP请求)的角度
还是刚才打电话问书店老板的例子
阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果;
如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你无关。
同步异步、阻塞非阻塞的综合例子——用水壶烧水
同步阻塞:坐在普通水壶前,坐着不做其他事直到水烧开
同步非阻塞:水烧开之前我们先去客厅看电视了,但是水壶不会主动通知我们,需要我们时不时的去厨房看一下水有没有烧开
异步阻塞:带有提醒功能的水壶烧水,我们坐着等
异步非阻塞:带有提醒功能的水壶烧水。在水烧发出提醒之前我们先去客厅看电视了,等水壶发出声音提醒我们。
以上内容笔记来自学习慕课网——Java并发编程的“基石”——多线程概念初识 链接:https://www.imooc.com/learn/1186
建议有时间可以看下视频,里面有很多概念以图的形式呈现,生动形象,感谢悟空老师!!!
思维导图地址:https://naotu.baidu.com/file/b8a70ff9e7f3af1437594b2d0fb4ebfd?token=11150672c00909cb