一个线程可以包含多个进程进程和线程的区别(超详细)
⽂章⽬录
进程和线程
进程
⼀个在内存中运⾏的应⽤程序。每个进程都有⾃⼰独⽴的⼀块内存空间,⼀个进程可以有多个线程,⽐如在Windows系统中,⼀个运⾏的xx.exe就是⼀个进程。
线程
进程中的⼀个执⾏任务(控制单元),负责当前进程中程序的执⾏。⼀个进程⾄少有⼀个线程,⼀个进程可以运⾏多个线程,多个线程可共享数据。
与进程不同的是同类的多个线程共享进程的堆和⽅法区资源,但每个线程有⾃⼰的程序计数器、虚拟机栈和本地⽅法栈,所以系统在产⽣⼀个线程,或是在各个线程之间作切换⼯作时,负担要⽐进程⼩得多,也正因为如此,线程也被称为轻量级进程。
Java 程序天⽣就是多线程程序,我们可以通过 JMX 来看⼀下⼀个普通的 Java 程序有哪些线程,代码如下。
public class MultiThread {
public static void main(String[] args){
// 获取 Java 线程管理 MXBean
ThreadMXBean threadMXBean = ThreadMXBean();
// 不需要获取同步的 monitor 和 synchronizer 信息,仅获取线程和线程堆栈信息
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false,false);
// 遍历线程信息,仅打印线程 ID 和线程名称信息
for(ThreadInfo threadInfo : threadInfos){
System.out.println("["+ ThreadId()+"] "+ ThreadName());
}
}
}
上述程序输出如下(输出内容可能不同,不⽤太纠结下⾯每个线程的作⽤,只⽤知道 main 线程执⾏ main ⽅法即可):
[6] Monitor Ctrl-Break //监听线程转储或“线程堆栈跟踪”的线程
[5] Attach Listener //负责接收到外部的命令,⽽对该命令进⾏执⾏的并且把结果返回给发送者
[4] Signal Dispatcher // 分发处理给 JVM 信号的线程
[3] Finalizer //在垃圾收集前,调⽤对象 finalize ⽅法的线程
[2] Reference Handler //⽤于处理引⽤对象本⾝(软引⽤、弱引⽤、虚引⽤)的垃圾回收的线程
[1] main //main 线程,程序⼊⼝
从上⾯的输出内容可以看出:⼀个 Java 程序的运⾏是 main 线程和多个其他线程同时运⾏。
进程与线程的区别总结
线程具有许多传统进程所具有的特征,故⼜称为轻型进程(Light—Weight Process)或进程元;⽽把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有⼀个线程的任务。在引⼊了线程的操作系统中,通常⼀个进程都有若⼲个线程,⾄少包含⼀个线程。
根本区别:进程是操作系统资源分配的基本单位,⽽线程是处理器任务调度和执⾏的基本单位
资源开销:每个进程都有独⽴的代码和数据空间(程序上下⽂),程序之间的切换会有较⼤的开销;线程可以看做轻量级的进程,同⼀类线程共享代码和数据空间,每个线程都有⾃⼰独⽴的运⾏栈和程序计数器(PC),线程之间切换的开销⼩。
包含关系:如果⼀个进程内有多个线程,则执⾏过程不是⼀条线的,⽽是多条线(线程)共同完成的;线程是进程的⼀部分,所以线程也被称为轻权进程或者轻量级进程。
内存分配:同⼀进程的线程共享本进程的地址空间和资源,⽽进程之间的地址空间和资源是相互独⽴的
影响关系:⼀个进程崩溃后,在保护模式下不会对其他进程产⽣影响,但是⼀个线程崩溃整个进程都死掉。所以多进程要⽐多线程健壮。
执⾏过程:每个独⽴的进程有程序运⾏的⼊⼝、顺序执⾏序列和程序出⼝。但是线程不能独⽴执⾏,必须依存在应⽤程序中,由应⽤程序提供多个线程执⾏控制,两者均可并发执⾏
从 JVM ⾓度说进程和线程之间的关系(重要)
图解进程和线程的关系
下图是 Java 内存区域,通过下图我们从 JVM 的⾓度来说⼀下线程和进程之间的关系。
从上图可以看出:⼀个进程中可以有多个线程,多个线程共享进程的堆和⽅法区 (JDK1.8 之后的元空间)资源,但是每个线程有⾃⼰的程序计数器、虚拟机栈 和 本地⽅法栈。
程序计数器为什么是私有的?
程序计数器主要有下⾯两个作⽤:
1. 字节码解释器通过改变程序计数器来依次读取指令,从⽽实现代码的流程控制,如:顺序执⾏、选择、循环、异常处理。
2. 在多线程的情况下,程序计数器⽤于记录当前线程执⾏的位置,从⽽当线程被切换回来的时候能够知道该线程上次运⾏到哪⼉了。
需要注意的是,如果执⾏的是 native ⽅法,那么程序计数器记录的是 undefined 地址,只有执⾏的是 Java 代码时程序计数器记录的才是下⼀条指令的地址。
所以,程序计数器私有主要是为了线程切换后能恢复到正确的执⾏位置。
虚拟机栈和本地⽅法栈为什么是私有的?
虚拟机栈:每个 Java ⽅法在执⾏的同时会创建⼀个栈帧⽤于存储局部变量表、操作数栈、常量池引⽤等信息。从⽅法调⽤直⾄执⾏完成的过程,就对应着⼀个栈帧在 Java 虚拟机栈中⼊栈和出栈的过程。
本地⽅法栈:和虚拟机栈所发挥的作⽤⾮常相似,区别是: 虚拟机栈为虚拟机执⾏ Java ⽅法 (也就是字节码)服务,⽽本地⽅法栈则为虚拟机使⽤到的 Native ⽅法服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合⼆为⼀。
所以,为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地⽅法栈是线程私有的。
⼀句话简单了解堆和⽅法区
堆和⽅法区是所有线程共享的资源,其中堆是进程中最⼤的⼀块内存,主要⽤于存放新创建的对象 (所有对象都在这⾥分配内存),⽅法区主要⽤于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
多进程和多线程区别
多进程:操作系统中同时运⾏的多个程序
多线程:在同⼀个进程中同时运⾏的多个任务
举个例⼦,多线程下载软件,可以同时运⾏多个线程,但是通过程序运⾏的结果发现,每⼀次结果都不⼀致。 因为多线程存在⼀个特性:随机性。造成的原因:CPU在瞬间不断切换去处理各个线程⽽导致的,可以理解成多个线程在抢CPU资源。
多线程提⾼CPU使⽤率
多线程并不能提⾼运⾏速度,但可以提⾼运⾏效率,让CPU的使⽤率更⾼。但是如果多线程有安全问题或出现频繁的上下⽂切换时,运算速度可能反⽽更低。
Java中的多线程
Java程序的进程⾥有⼏个线程:主线程,垃圾回收线程(后台线程)等
在 Java 中,当我们启动 main 函数时其实就是启动了⼀个 JVM 的进程,⽽ main 函数所在的线程就是这个进程中的⼀个线程,也称主线程。
Java⽀持多线程,当Java程序执⾏main⽅法的时候,就是在执⾏⼀个名字叫做main的线程,可以在main⽅法执⾏时,开启多个线程
A,B,C,多个线程 main,A,B,C同时执⾏,相互抢夺CPU,Thread类是java.lang包下的⼀个常⽤类,每⼀个Thread类的对象,就代表⼀个处于某种状态的线程

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。