进程与线程

进程

程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至cpu,数据加载至内存。在指令运行过程中还需要磁盘网络等设备。进程就是用来加载指令、管理内存、管理IO的

当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。

进程就可以视为程序的一个实例。大部分程序可以运行多个实例进程(例如记事本 、画图、浏览器),也有的程序只能启动一个实例进程(例如网易云音乐、360安全卫士)

线程

一个进程之内可以分为一到多个线程。

一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行。

Java中,线程作为最小调度单位,进程作为资源分配的最小单位。在Windows中进程是不活动的,只是作为线程的容器

二者对比

进程基本上是相互独立的,而线程存在于内存内,是进程的一个子集。

进程拥有共享的资源,如内存空间等,仅其内部的线程共享。

进程间通信较为复杂

        同一台计算机的进程通信称为IPC

不同计算机的进程通信,需要通过网络,并遵守不同的协议,例如HTTP

线程通信相对简单,因为他们共享进程内的内存,一个例子是:多个线程可以访问同一个共享变量

线程更轻量,线程上下文切换成本一般比进程上下文切换低

并发

一般将线程轮流使用CPU中的单个核心的做法称为并发,concurrent,同一时间应对(dealing with)多件事情的能力

并行

一般计算机都是多核心,多个核心同时执行线程的做法称为并行。parallel,统一时间对手做(doing)多件事情的能力。

在一般情况下,计算机的核心线程数大于核心数,当执行的线程数多余计算机的线程数时,称之为并发和并行同时存在。这种情况比较多见。

应用

设计:多线程可以让方法执行变为异步的(不要巴巴干等着方法的返回值)比如说读取磁盘文件时,假设读取花费了5秒,如果没有线程调度机制,这5秒里调用者什么都做不了,其他代码都得暂停。

结论:比如在项目中,视频文件需要转格式等操作比较费时,这时开启一个新的线程处理视频的转换,避免阻塞主线程。tomcat的异步servlet也是类似的目的,让用户线程处理耗时较长的操作,避免阻塞tomcat的工作线程。ui程序中开线程进行其他操作,避免阻塞ui线程

原理之线程运行

栈与帧

我们都知道JVM中由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟机就会为其分配一块栈内存。

每个栈由多个帧(Frame)组成,对应着每次方法调用时所占用的内存。

每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。

每个线程运行时虚拟机都会为其开辟一个自己的独立栈,线程间栈帧内存是独立的。

线程上下文切换

因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码 线程的 cpu 时间片用完 垃圾回收 有更高优先级的线程需要运行 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法 当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念 就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的 状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等 Context Switch 频繁发生会影响性能。

常见方法

start,run,getState

@Slf4j
public class Test5 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            log.debug("t1-running");
        }, "t1");
        System.out.println(thread.getState());//打印线程状态

        thread.start();
        log.debug("main-running");
        System.out.println(thread.getState());//线程开启后在此打印状态
    }
}

由下图可以看到在调用start前,先new了一个线程,调用后打印出runnable对象,getState方法可以查看线程状态,一个线程不能连续调用2次start方法,否则抛非法调用异常。        

sleep 与 yield

sleep

1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)

2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException

3. 睡眠结束后的线程未必会立刻得到执行

4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性

yield

1. 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程

2. 具体的实现依赖于操作系统的任务调度器 线程优先级 线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它 如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在C语言进程线程是并发编程重要的概念。进程(Process)是操作系统分配资源的基本单位,它具有独立的地址空间和系统资源,可以独立运行。而线程(Thread)则是进程的一个执行单元,是进程内部的一个分支,与同一进程的其他线程共享地址空间和系统资源。 进程线程的区别主要体现在以下几个方面: 1. 资源开销:进程的资源开销较大,每个进程都有独立的内存空间、文件描述符等系统资源。而线程进程共享同一进程的资源,因此线程的资源开销较小。 2. 并发性:进程是独立运行的实体,进程间通过进程间通信(IPC)进行数据交换。而线程是在同一进程内并发执行的,它们共享进程的数据和资源,因此线程的并发性较高。 3. 调度和切换:进程切换涉及到上下文切换,需要保存和恢复进程的执行状态,开销较大。而线程的切换只涉及到线程的调度,开销较小。 4. 同步与通信:进程之间的通信和同步需要通过IPC机制,如管道、消息队列、信号量等。而线程之间可以通过共享内存和互斥量等方式进行同步和通信,开销较小。 总之,进程线程在资源开销、并发性、调度和切换、同步与通信等方面有着不同的特点和适用场景。在C语言,通过使用多线程技术可以实现并发编程,提高程序的效率和性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++多线程----进程线程区别](https://blog.csdn.net/weixin_43956732/article/details/109736126)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

weixin明诚

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

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

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

打赏作者

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

抵扣说明:

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

余额充值