进程与线程

mac2022-06-30  30

概述

几乎任何操作系统都支持运行多个任务,通常一个任务就是一个程序,一个程序就是一个进程,当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程。

进程

进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个单位,当程序进入内存运行时,即为进程。

进程的三个特点

1、独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每个进程都有自己独立的地址空间2、动态性:进程和程序的区别在于进程是动态的,进程中有独立的时间概念,进程具有自己的生命周期和各种不同状态。

3、并发性:多个进程可以在单个处理器上并发执行,互不影响。

并发:通过CPU调度算法,让用户看上去同时执行,实际上从CPU操作层面上不是真正的同时并行:多个CPU实例或者多台机器同时执行一段处理逻辑,是真正的同时

进程间的通信方式

1、管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用,进程间的亲缘关系通常是指父子进程关系;2、有名管道:有名管道也是半双工的通信方式,但是它允许无亲缘关系的进程间的通信;3、无名管道:无名管道也是半双工的通信模式,只能用于具有亲缘关系的进程之间的通信,具有固定的读端和写端4、信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问,它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段5、消息队列:消息队列是由消息的链表,存放在内核中并有消息队列标识符标识,消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点6、信号:信号是一种比较复杂的同行方式,用于通知接收进程某个 事件已经发生7、共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,8、套接字:也是一种进程间的通信方式,与其他通信机制不同的是,他可用于不同及其间的进程通信

线程

线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程,线程可以拥有自己的堆栈,自己的程序计数器和局部变量表,但不能拥有系统资源它与父进程的其他线程共享该进程的所有资源。

创建线程的三种方式

1、继承Thread类创建线程类

(1)、定义Thread类的子类,并重写该类的run方法,该方法的方法体就代表了线程要完成的任务,因此把run方法称为执行体(2)、创建Thread子类的实例,即创建了线程对象。(3)、调用线程对象的start()方法来启动线程。

2、实现runnable接口创建线程类

(1)、定义runnable接口的实现类,并重写该接口的run()方法(2)、创建runnable实现类的实例,并以此实例作为Thread的目标来创建Thread对象,该Thread对象才是真正的线程对象(3)、调用线程对象的start()方法来启动线程

3、实现callable接口方式创建线程类

(1)、创建callable接口的实现类,并实现call()方法,该方法将作为线程执行体,并且有返回值;(2)、创建callable实现类的实例,使用FutureTask对象封装Callable对象call()方法的返回值(3)、使用FutureTask对象作为Thread对象Target创建并启动新线程(4)、调用FutureTask对象的get()方法来获得线程执行结束后的返回值

Runnable、Callable、Thread的对比

1、线程类实现了Runnable、Callable接口,还可以实现其他类,而继承Thread类后就不能继承其他类了;2、使用Runnable、Callable接口创建线程,多个线程可以共享同一个target对象,所以非常适合多个相同的线程来处理同一个资源的的情况,从而可以将CPU、代码、数据分开,形成清晰的模型,较好的体现了面向对象的思想。3、实现Runnable接口没有返回值,而实现Callable有返回值

线程状态

1、新建状态(New):新创建了一个线程对象2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法,该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权3、运行状态(Running):就绪状态的线程获取了CPU,执行了程序代码;

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权, 暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态

(1)、等待阻塞:运行的线程执行wait()方法时,JVM会把线程放入等待池中;(2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程占用,则JVM会把该线程放入锁池中(3)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出I/O请求时,JVM会把该线程置为阻塞状态,当sleep()状态超时,join()等待线程终止或超时,或者I/O处理完毕时,线程重新载入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出run()方法,该线程结束生命周期

为什么有了进程还要线程?

用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括表格、内存空间、磁盘空间、I/O设备等,然后把该进程放入进程的就绪队列,进程调度程序选中它,为它分配CPU和其他有关资源,该进程才真正运行。所以开启进程的开销较大

引入线程的好处

易于调度提高并发性,通过线程可方便有效实现并发性,进程可创建多个线程来执行同意程序的不同部分开销少,创建线程比创建进程要快,所以开销少利于充分发挥多处理器的功能,通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。对于线程是作为调度和分派的基本单位,不同时作为独立分配资源的单位,以使之轻装运行,而对拥有资源的基本单位,又不频繁地对之进行切换

转载于:https://www.cnblogs.com/qizc/p/10760663.html

最新回复(0)