赞
踩
什么是进程?
简单来说,
进程就是程序的一次启动和执行
。进程是操作系统中的一个概念,它代表正在运行的程序的实例
。每个进程都有自己的内存空间
、代码和数据
,以及其他操作系统资源
,如文件和设备。进程之间是相互独立的,它们不能直接访问彼此的内存空间,但可以通过特定的机制进行通信。什么是程序?
程序是一组指令的集合
,用来完成特定任务或解决特定问题的一系列计算机代码。程序通常存储在文件中,包括可执行文件或源代码
文件。**进程和程序有什么关系?
从使用者角度来说明,一个程序可以启动多次,那么就会对应多个进程,例如我们在使用浏览器的时候,可以启动很多个浏览器。
从开发者角度来说明,程序是开发人员编写的
源代码
和二进制文件
,但程序本身是静态的,它只是存在于磁盘或其他存储设备中,并不具有执行的能力。 而**进程 是 程序在计算机上运行的实例**
进程一般,是由程序段,数据段,进程控制块三个部分组成
早期的操作系统确实没有线程的概念,只有进程。在早期的操作系统中,进程是最小的资源分配单位,每个进程拥有独立的地址空间和资源,通过操作系统的调度器进行调度和管理。后来随着计算机的发展,CPU的性能越来越高,为了提高CPU的利用率,进程内部演进并发调度的诉求,于是就发明了线程。
线程指的是,进程代码段的一次顺序的执行流程,线程是CPU调度的最小单位,一个进程可以有多个线程,各个线程之间共享进程的内存空间、系统资源
进程仍然是操作系统的资源的分配的最小单位
在Java程序中当你启动一个Java程序时,实际上会启动至少两个线程。
- 主线程(Main Thread):这是程序开始执行时默认启动的线程,它是程序的入口点。主线程负责执行
main()
方法中的代码,并且在main()
方法执行完毕后,主线程也会随之结束。- 虚拟机线程(JVM Thread):除了主线程之外,Java虚拟机还会启动其他一些线程,用于执行不同的任务,例如垃圾回收、JIT编译、线程调度等。这些线程通常由Java虚拟机自动管理,开发者不需要过多地关注它们。
线程的基本信息
需要注意,在Java中,虽然可以通过设置线程优先级来影响线程调度器的行为,但是最终的调度取决于底层操作系统和Java虚拟机的具体实现。Java线程优先级只是给线程调度器一个提示,告诉它哪些线程可能更重要或更紧急,但并不能保证线程会按照指定的优先级顺序执行。实际上,线程优先级在不同的操作系统和不同的Java虚拟机中可能会有不同的行为
新建
,就绪
,阻塞
,运行
,结束
,等状态中的一种*程序计数器
下面的同过一个简单的程序,来看一下,Java中线程的基本信息
public static void main(String[] args) { // 创建一个线程 打印出线程所有的基本信息 Thread thread = new Thread(() -> { logger.error("=============== 线程启动了!=================="); }, "线程1"); // 启动线程 thread.start(); logger.error("线程的id:{}",thread.getId()); logger.error("线程的名称:{}",thread.getName()); logger.error("线程的优先级:{}",thread.getPriority()); logger.error("线程的状态:{}",thread.getState()); logger.error("线程的线程组:{}",thread.getThreadGroup()); logger.error("线程的是否是守护线程:{}",thread.isDaemon()); logger.error("线程的是否是活跃的:{}",thread.isAlive()); logger.error("线程的是否是中断的:{}",thread.isInterrupted()); }
栈内存(Stack Memory)是计算机内存中的一种重要的内存分配方式,它主要用于存储函数调用时的局部变量、函数参数、函数调用返回地址以及一些临时数据。栈内存的管理是由编译器自动完成的,它的特点是后进先出(LIFO,Last In First Out)的数据结构。
栈帧(Stack Frame)是在函数调用时在栈内存中创建的一个内存块,用于存储函数的参数、局部变量、返回地址以及其他与函数执行相关的信息。每次函数调用时,都会创建一个新的栈帧,函数执行结束后,该栈帧会被销毁,从而释放相应的内存空间。
以下是栈帧的详细介绍:
栈帧(Stack Frame)是在函数调用时在栈内存中创建的一个内存块,用于存储函数的参数、局部变量、返回地址以及其他与函数执行相关的信息。每次函数调用时,都会创建一个新的栈帧,函数执行结束后,该栈帧会被销毁,从而释放相应的内存空间。以下是栈帧的详细介绍:
通过一个案例来了解一下栈帧
这是基础函数调用 计算数值累加的方法,下面通过这个方法来具体了解一下栈帧
public class ThreadStackDemo { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final ReentrantLock lock = new ReentrantLock(); private static final Condition condition = lock.newCondition(); public static void main(String[] args) throws InterruptedException { int a = 1; int b = 1; Res res = add(a, b); logger.error("res:{}", res.getData()); } public static Res add(int a, int b) { Res res = new Res(); int c = a + b; res.setData(c); logger.error("c:{}", c); return res; } } @Getter @Setter class Res{ private int data; }
这段代码的执行原理:
main()
方法。main()
方法中,首先声明了两个整型变量 a
和 b
,它们被分配在 main()
方法的栈帧中。add(a, b)
方法,这个方法调用会创建一个新的栈帧并压入调用栈。add()
方法被调用时,JVM在调用栈上创建一个新的栈帧用于执行该方法。add()
方法内部,声明了一个 Res
对象 res
,它被分配在 add()
方法的栈帧中。c
,也被分配在 add()
方法的栈帧中。a + b
,将结果赋值给 c
。res.setData(c)
方法,这个方法调用会在当前栈帧中执行。res
对象。add()
方法执行完毕后,将返回到 main()
方法。main()
方法中,接收 add()
方法返回的 Res
对象,并将其赋值给 res
。logger
输出结果。main()
方法执行完毕后,主线程的栈帧被销毁。main()
方法的结束,整个程序执行结束,JVM 会关闭。在Java中,线程可以处于不同的状态,这些状态反映了线程在其生命周期中的不同阶段和行为。
start()
方法启动线程。在新建状态下,线程并不会占用系统资源。start()
方法,但是还没有被分配到 CPU 时间片,即线程处于就绪队列中等待系统调度执行。处于就绪状态的线程可能随时被调度执行,取决于操作系统的调度算法。Object.wait()
方法、Thread.join()
方法,或者调用了一些阻塞方法时会进入等待状态。Thread.sleep()
、Object.wait(timeout)
方法,或者调用了带有超时参数的 Thread.join(timeout)
方法时会进入超时等待状态。线程和进程是操作系统中管理和调度的两个基本概念,它们之间有着明显的区别:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。