细说进程与线程

目录

一、进程

1、进程的概念

2、进程的特点

1)独立性

2)动态性

3)并发性

二、串行、并行、并发

1、串行、并行

2、并行、并发

3、并行与并发的关系

4、高并发

三、线程

四、线程和进程有何异同

1、线程和进程的不同之处

1)起源不同

2)概念不同

3)内存共享方式不同

4)拥有的资源不同

5)数量不同

6)开销不同

2、线程和进程的相同之处

五、多线程

1、Java语言和多线程的渊源和关系

2、多线程的概念

3、为什么需要多线程

4、线程执行的时机

5、线程的随机性

6、多线程的使用场景

7、多线程的局限

六、线程的几种状态以及状态之间的切换

1、线程的几种状态

2、五态模型

3、五态模型

七、创建多线程的三种方式

1、三种方式

2、Thread、Runnable两种实现方式的比较

八、多线程的安全问题

1、说明

2、同步锁

1)异步与同步

2)解决线程安全问题的方案--- synchronized同步关键字

九、关于多线程的常见面试题


一、进程

1、进程的概念

        进程就是正在运行的程序,它代表了程序所占用的内存区域。

2、进程的特点

1)独立性

        进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间。

2)动态性

        进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合,程序加入了时间的概念以后,称为进程,具有自己的生命周期和各种不同的状态,这些概念都是程序所不具备的。

3)并发性

        多个进程可以在单个处理器CPU上并发执行,多个进程之间不会互相影响。

二、串行、并行、并发

1、串行、并行

        串行是大家排队一个一个来,并行是大家一起来。

2、并行、并发

         HA(High Availability)高可用:指在高并发的情景中,尽可能的保证程序的可用性,减少系统不能提供服务的时间

3、并行与并发的关系

        并行一定是并发,并发不一定是并行。

4、高并发

  1. 概念

        多个进程抢占公共资源(例如售票案例、双十一)。

     2.高并发有哪些指标

  • QPS(Queries Per Second):每秒查询数
  • 带宽
  • PV(Page View)
  • UV(Unique Visitor)
  • 并发连接数
  • 服务器平均请求等待时间        

三、线程

  1. 线程是进程进行运算调度的最小单位
  2. 一个进程可以开启多个线程,一个进程也可以只包含一个线程--单线程程序
  3. 线程拓展了多进程,也就是一个进程可以干多件事情
  4. 每个线程拥有自己独立的内存空间,多个线程之间也存在共享数据

四、线程和进程有何异同

1、线程和进程的不同之处

1)起源不同

        先有进程,后有线程(目的是为了提高执行效率)。

2)概念不同

  1. 进程:具有独立功能的、正在运行的一个程序(系统分配资源和调度的一个单位)。
  2. 线程:线程是进程(CPU)进行运算调度的最小单位。

3)内存共享方式不同

  1. 进程:不同的进程会被分配到不同的内存,但是不同进程之间的内存通常是不共享的(比如说浏览器、QQ、微信之间互不共享)。
  2. 线程:本身就服务于同一个进程,所以线程之间互相通信是十分容易的。

4)拥有的资源不同

  1. 线程共享的资源:
  • 进程代码块
  • 进程的共有数据(利用这些共享的数据,线程很容易的实现相互通信)
  • 进程的打开的文件描述符
  • 信号的处理器
  • 进程的当前目录
  • 进程用户ID与进程组ID
  1. 线程独有的内容包括:
  • 线程ID
  • 寄存器组的值
  • 线程的堆栈
  • 错误的返回码
  • 线程的信号频闭码

5)数量不同

        一个进程可以有多个线程(至少要有一个)。

6)开销不同

  1. 线程的创建、终止时间比进程短
  2. 同一进程内的线程切换时间比进程切换时间短
  3. 统一进程的各个线程时间共享内存和文件资源,可以不通过内核进行通信

2、线程和进程的相同之处

  1. 进程和线程都有ID/寄存器组、状态和优先权、信息块
  2. 创建后都可更改自己的属性
  3. 都可与父进程共享资源
  4. 都不直接访问其他无关进程或线程的资源

五、多线程

1、Java语言和多线程的渊源和关系

  1. Java设计之初就支持多线程,相比于当时的其他编程语言,十分具有优势。
  2. Java语言在服务器端开发语言中的地位--常年高居前三。
  3. 一对一映射到操作系统的内核线程。
  4. JVM会自动启动线程,即使代码中不显示创建线程,在运行main时,JVM也会自动启动其他的线程,测试如下:
  • 测试代码:

  • 打断点,debug模式运行,查看控制台信息,会发现,除了main,还自动启动了其他线程:

  Signal Dispatcher:将操作系统发来的信号分发给适当的处理程序。
  Finalizer:负责对象的finalize()方法,随着java语言的发展,不再推荐使用。
  Rrference Handler:和GC(垃圾回收),引用相关的线程。

2、多线程的概念

  1. 宏观层面上:多个线程看起来是同时在运行。
  2. 微观层面上:一个CPU同一时刻只能处理一件事,至于哪个时刻执行哪个线程,取决于OS底层的算法(FCFS/SJS......)。

3、为什么需要多线程

  1. 最主要的目的就是提高CPU利用率
  2. 避免无效等待(IO的时候可以做别的事)
  3. 提高用户体验:避免卡顿、缩短等待时间
  4. 便于编程建模

4、线程执行的时机

        OS选中它,并给它分配时间片(允许OS执行当前线程的一段时间);没有时间片的线程是挂起(暂停/冻结)的状态,等待再次被分配时间片才能运行。

5、线程的随机性

        多个线程的执行效果是不可控的,因为CPU会调度处理,结果具有随机性;至于那个时间片执行哪一个线程,时间片有多长,我们都控制不了。

6、多线程的使用场景

        为了同时做多件不同的事:比如说打开网页的同时听音乐、后台定时任务。

7、多线程的局限

  1. 性能问题:上下文切换带来的消耗。
  2. 异构化任务(任务结构不一样)很难高效并行。
  3. 带来的线程安全问题:包括数据安全问题(例如i++总数不一致)活跃性问题(线程饥饿、死锁)。

六、线程的几种状态以及状态之间的切换

1、线程的几种状态

  1. 创建状态:申请PCB,然后为该线程运行分配必须的资源(对应方法:new)。
  2. 就绪(可运行)状态:将该线程转为就绪状态插入到就绪队列中(对应方法:start())。
  3. 执行(运行)状态:线程被OS选中,分配时间片正常运行程序,时间片用完挂起加入到就绪队列当中,等待OS下一次选中。
  4. 阻塞状态:正在运行的线程由于某些事件(I/O请求等)暂时无法执行的状态,即线程执行阻塞(锁阻塞/休眠10ms)。
  5. 终止状态:归还PCB,对应的空间清除。

2、三态模型

  1.  就绪 → 执行:为就绪线程分配CPU即可变为执行状态"。
  2. 执行 → 就绪:正在执行的线程由于时间片用完被剥夺CPU暂停执行,就变为就绪状态。
  3. 执行 → 阻塞:由于发生某事件,使正在执行的线程受阻,无法执行,则由执行变为阻塞。
  4. (例如线程正在访问临界资源,而资源正在被其他线程访问)。
  5. 反之,如果获得了之前需要的资源,则由阻塞变为就绪状态,等待分配CPU再次执行。

3、五态模型

七、创建多线程的三种方式

1、三种方式

  1. 继承Thread
  2. 实现Runnable接口
  3. 线程池:
  • Executors :辅助创建线程池的工具类
  • newFixedThreadPool(int nThreads) :指定线程池数n
  • ExecutorService:用来存储线程的池子,把新建线程/启动线程/关闭线程的任务都交给池来管理
  • pool.execute:(目标业务对象target) 把任务丢到线程池

2、Thread、Runnable两种实现方式的比较

  1. 继承Thread类:
  • 优点: 编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。
  • 缺点: 自定义的线程类已继承了Thread类,所以后续无法再继承其他的类。
  1. 实现Runnable接口:
  • 优点: 自定义的线程类只是实现了Runnable接口或Callable接口,后续还可以继承其他类,在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码、还有数据分开(解耦),形成清晰的模型,较好地体现了面向对象的思想。
  • 缺点: 编程稍微复杂,如想访问当前线程,则需使用Thread.currentThread()方法。

八、多线程的安全问题

1、说明

  1. 多线程安全问题是如何出现的?

         常见情况是由于线程的随机性+访问延迟。

  1. 如何判断程序有没有线程安全问题?

        在多线程程序中 + 有共享数据 + 多条语句操作共享数据

2、同步锁

1)异步与同步

  • 同步:体现了排队的效果,同一时刻只能有一个线程独占资源,其他没有权利的线程排队。坏处就是效率会降低,不过保证了安全。

  • 异步:体现了多线程抢占资源的效果,线程间互相不等待,互相抢占资源。坏处就是有安全隐患,但是效率要高一些。

2)解决线程安全问题的方案--- synchronized同步关键字

  1. 写法格式:
  • 如果是实现接口的方式:

synchronized (锁对象){ 
需要同步的代码(也就是可能出现问题的操作共享数据的多条语句);
}
//锁对象:不限制类型,唯一就行,一般是Object o = new Object()

  • 如果是实现类的方式:

synchronized (锁对象){ //
需要同步的代码(也就是可能出现问题的操作共享数据的多条语句);
}
//锁对象一般是 类名.class ,目的就是为了锁的唯一

    2.同步效果的使用有两个前提:

  • 同步需要两个或者两个以上的线程(单线程无需考虑多线程安全问题)。
  • 多个线程间必须使用同一个锁(我上锁后其他人也能看到这个锁,不然我的锁锁不住其他人,就没有了上锁的效果)。

九、关于多线程的常见面试题

  1. 进程和线程的相同和不同?
  2. 并行和并发的异同?
  3. 高并发是不是意味着多线程?有什么反例?

高并发是一种状态,多线程是一种解决方案,高并发并不意味着多线程。

比如:当前要解决数据库的高并发问题,很多请求同时到达数据库,数据库承受不了这样的压力,针对于这种情况,加一个redis缓存层。这种情况下,会优先访问redis,redis会将大量的压力承受下来,减轻数据库的压力。高并发并不意味着多线程。 redis吞吐量大,高并发,却是单线程。
     4.多线程可以提高程序执行效率,你知不知道有哪些弊端?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Righter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值