浅谈操作系统中的重要概念——线程

文章目录

  • 一、进程概念产生的原因
  • 二、进程的弊端
  • 三、线程
    • 3.1、线程复用结构体PCB
    • 3.2、多线程弊端
      • 3.2.1、拖慢程序的效率
      • 3.2.2、产生线程安全问题
      • 3.2.3、导致整个进程终止
    • 3.3、怎么判断一个线程是否执行完毕??
    • 3.4、怎么终止一个线程??
  • 四、进程与线程的区别及联系[高频面试题]
  • 五、线程的弊端
  • 六、解决线程弊端的方法
    • 6.1 协程/纤程
    • 6.2、线程池
  • 七、在Java代码中创建线程的方法
  • 八、后台线程与前台线程[这两概念还是蛮重要的]

一、进程概念产生的原因

引入进程其实是为了满足“并发编程”的需求(此处的并发=并行+并发)。随着时代发展,技术越来越成熟,cpu 逐渐变成多个核心,此时应用程序(软件)也需要做出对应的调整,让代码能够支持多核心cpu,即在代码中可以把多核心充分利用起来。(硬件发展,软件也要跟上)

二、进程的弊端

多进程已经很好的实现了 “并发编程” 的效果,但是还是具有明显的缺点:进程比较厚重。具体表现在:
1、消耗过多系统资源
2、速度更慢
进程运行需要消耗资源,如果是在频繁的创建以及销毁(申请/释放资源)的情况下(服务器里会这样频繁操作),开销就会很大,系统压力也会很大,运行效率也会降低。

此时为了能够保留进程 “并发编程” 的效果,并且还能提升其 创建/销毁 的速度,就引入了 线程

三、线程

最初是尝试在创建进程时,只给进程分配一个简单的PCB,而不去分配后续进程运行时所需的系统资源,此时这类进程称作——轻量级进程(也叫做 线程 Thread),但是这样的尝试还是出现一个问题:线程创建出来,也是为了到cpu上执行,完成相关任务的。执行时就需要依靠系统分配给的资源进行运行,但是此时只简单分配了一个PCB,没给资源,这样创建出来的线程也没办法进行 “并发编程”,违背了初衷,这个尝试以失败告终。

此时第二次尝试:还是创建进程,但创建进程的时候,将进程运行时用到的系统资源分配好,后续再在进程内部创建线程,此时创建出来的进程内部的线程,直接复用了进程里面已经分配好的资源。

刚创建出来的进程,可以视为是一个只包含一个线程的进程(此时创建的过程需要分配资源,因此此时第一个线程创建的开销就可能比较大,后面再在这个进程里创建的线程,直接服用当前进程的资源,开销就比较小)

一个进程,至少包含一个线程,也可以包含多个线程。这些线程各自独立的在 cpu 上进行调度,因此线程既能够完成 “并发编程” 的效果,又可以以比进程更轻量的方式运行。

举个例子,加深一下对线程的理解:
在这里插入图片描述
在这里插入图片描述

3.1、线程复用结构体PCB

前面我们知道了系统使用结构体PCB描述进程,PCB又叫做进程控制块。那使用什么结构体描述线程呢??还是使用PCB描述线程。

在 Windows 操作系统中,描述进程和线程是使用不同的结构体,但是在 Linux 操作系统中,复用了PCB这个结构体,来描述线程。此时,一个PCB 对应 一个线程,多个 PCB 对应一个 进程

由于同一个进程中的多个线程共用进程里的同一份资源(内存资源、硬盘资源),因此同一个进程中的多个PCB里的内存指针、文件描述符表,这两个字段的内容都是一样的。

但是每个线程独立到cpu上调度,因此这些PCB里的状态、优先级、上下文、记账信息…都是各不相同,各有一份的。

因此此时我们知道:
1、进程是系统分配资源的基本单位。
2、线程式系统进行调度执行的基本单位。

3.2、多线程弊端

虽然线程比进程更轻量,但也并不是一点资源都不消耗。并且也不是一个进程中创建的线程越多越好(多线程)。

举个例子说明原因:

3.2.1、拖慢程序的效率

在这里插入图片描述
对于线程来说也是一样的,线程太多的时候,其调度的开销反而会拖慢整个程序的效率。

3.2.2、产生线程安全问题

在这里插入图片描述
对于线程来说也是一样的,线程太多的时候,就极有可能出现bug,即线程安全问题(多线程编码中,最关键的问题)。

3.2.3、导致整个进程终止

在这里插入图片描述
对于线程来说也是一样的,一旦某个线程执行过程中出现异常,并且这个异常不能很好的被解决掉的话,有可能殃及其他线程,甚至很有可能导致整个进程终止(进程中的所有线程也随之终止)。

所以多线程虽然比多进程相比,确实是有优势的(因为线程更轻量,创建销毁的速度更快),但是线程也有缺点(不像进程那么稳定,一旦某个线程出现问题,很容易殃及其他线程)。

多线程、多进程 本质上都是 “并发编程” 的实现模型,实际上还有许多其他的 “并发编程” 的实现模型。

3.3、怎么判断一个线程是否执行完毕??

对于主线程来说,main() 方法是其入口方法,如果 main() 方法里的代码逻辑执行完毕,那么主线程也就执行完毕了。对于其他我们创建出来的线程,run() 方法或者Lambda表达式里的代码逻辑执行完毕,那么这些线程也就执行完毕了。

3.4、怎么终止一个线程??

一个线程的 run() 方法执行完毕,就算终止(正常结束)了。

此处的终止线程,是借助别的手段,让 run() 方法能够尽快的执行完毕,因为正常情况下,是不会出现 run() 方法还没执行完毕,线程就突然没了的情况,除非是机器自动关机或者拔电源…但是还有一些人工干预的办法,譬如说如下方法:

1、程序员手动设置标志位。

public class testInterrupted {
//    设置标志位public static boolean isQuit = false;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while (!isQuit){System.out.println("hello world!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();Thread.sleep(2000);
//        修改标志位isQuit = true;} 
}

运行结果:
在这里插入图片描述
将死循环的线程提前终止了。

四、进程与线程的区别及联系[高频面试题]

1、进程包含线程。都是为了实现 “并发编程”,但线程比进程更轻量。
2、进程是系统分配资源的基本的单位,线程是系统进行调度执行的基本单位。
3、进程具有独立的地址空间,彼此之间不会相互影响,线程共用一份地址空间,容易相互影响导致整个进程由于异常结束。

五、线程的弊端

注意:上面提到的是 多线程的弊端,这里提到的是线程本身的弊端,这是两个概念,注意区分。

线程相较于进程来说的确是比较轻量的,但是也不是没有创建/销毁的成本。当遇上高并发服务器时,由于要处理的并发量太多了,需要频繁的 创建/销毁 线程,开销仍然不可忽视。

六、解决线程弊端的方法

那么有什么比线程更轻量或者开销更小的方法吗?

6.1 协程/纤程

1、为了解决这样的情况,有些程序员提出了 “轻量级线程” —— 协程/纤程 这样的概念。 但是由于只有一些第三方库实现了协程,Java标准库目前还没有内置关于协程的使用类,所以在Java中还没有开始大量使用协程这样的概念。

但是 Go语言 里天然支持协程,协程使用起来非常高效、方便。所以大家如果对协程有兴趣,可以深入学习一下 Go 语言。

6.2、线程池

池(pool)其实是计算机中非常经典的一个思想方法。

在程序中,我们通常会把一些要释放掉的资源先存放到一个 “池子里” ,预防后续可能会再次用到这些资源,但却无法找到的风险。

申请资源时,也是把要申请的资源提前申请好,存到一个 “池子里”,方便后续随取随用。

这个池子就是线程池。

七、在Java代码中创建线程的方法

点击此链接跳转至博客查看

八、后台线程与前台线程[这两概念还是蛮重要的]

后台线程(守护线程):后台线程不影响进程结束。一个进程中的前台线程都结束了,后台线程还没执行完,也会跟着进程的结束而退出。
前台线程:前台线程会影响进程的结束。如果前台线程还没结束,进程是无法结束的。

一般默认我们创建的线程,默认是 前台线程,不过在代码中我们可以通过方法 setDaemon()修改前台线程成后台线程。

/*** 将一个 前台线程 设置成 后台线程*/
public class testSetDaemon {public static void main(String[] args) {Thread t = new Thread(()->{while (true){System.out.println("hello world!");}});//        将 前台线程 设置成 后台线程t.setDaemon(true);t.start();}
}

运行结果:
在这里插入图片描述
没进行设置之前,我们都能猜到预期结果:创建出的新线程在循环打印hello world。

但是当将其设置成后台线程后,进程唰的一下就结束了,这是为啥??

这是因为设置后只剩下了main为入口方法的主线程是一个前台线程,由于main并没有什么代码需要执行,因此该前台线程很快就执行完毕了,此时后台线程即便没执行完毕,他也无法影响到进程的结束,也要跟着进程结束而退出执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/829668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习笔记二十八】EWM和QM集成的后台配置和前台展示

一、EWM和QM集成概述 SAP EWM(扩展仓库管理)和QM(质量管理)的集成是SAP系统中一个重要的特性,它允许企业在仓库管理过程中实现质量控制和检验流程的自动化。以下是关于EWM和QM集成的一些关键点概述: 集成优势:通过集成,企业可以确保仓库中的物料在收货、存储、…

csdn的复制代码功能如何实现

页面布局分析&#xff1a; 按钮在文本框里面&#xff0c;所以文本框是父元素&#xff0c;按钮是子元素。要使得按钮在文本框的右上角&#xff0c;需要使用绝对定位。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…

实现ALV页眉页脚

1、文档介绍 在ALV中&#xff0c;可以通过增加页眉和页脚&#xff0c;丰富ALV的展示。除了基本的页眉和页脚&#xff0c;还可以通过插入HTML代码的方式展示更加丰富的页眉和页脚&#xff0c;本篇文章将介绍ALV和OOALV中页眉页脚的使用。 2、ALV页眉页脚 效果如下 2.1、显示内…

长图高效切割新体验:支持按随机宽度灵活裁切,释放无限创意与效率

图像的传播已经成为我们日常生活的一部分。而长图&#xff0c;作为一种特殊的图像形式&#xff0c;其独特的展示方式能够吸引更多的目光。但是&#xff0c;如何将长图高效切割&#xff0c;以展现其独特的魅力呢&#xff1f;现在&#xff0c;我们为您带来了一款支持按随机宽度切…

怎么找回录音文件?这4个方法实用又简单!

“我有一份比较重要的录音文件保存在电脑上了&#xff0c;不知道是因为误删还是什么原因&#xff0c;这个文件丢失了&#xff0c;我现在有什么比较好的方法可以找回这个文件吗&#xff1f;” 录音文件是我们日常生活中经常使用的文件类型&#xff0c;无论是会议记录、学习笔记还…

论机器学习(ML)在网络安全中的重要性

机器学习是什么&#xff1f; 机器学习(ML)是人工智能的一个分支&#xff0c;它使用算法来使计算机系统能够自动地从数据和经验中进行学习&#xff0c;并改进其性能&#xff0c;而无需进行明确的编程。机器学习涉及对大量数据的分析&#xff0c;通过识别数据中的模式来做出预测…

MySQL/MariaDB 如何查看当前的用户

MySQL 的所有数据库用户信息是存储在 user 数据表中的。 可以在登录成功数据后运行 SQL&#xff1a; MariaDB [(none)]> select user,host from user;就可以查看到数据中的所有用户信息。 MariaDB [(none)]> select user,host from user; ERROR 1046 (3D000): No databa…

数据集笔记:geolife staypoint聚合的location 最近的10个其他location

数据集&#xff1a;处理geolife数据-CSDN博客 这边的stations&#xff0c;找到每个station 最近的其他10个station 1 读取数据 假设已经读完了&#xff0c;就是locations 2 保留有用的列 locations.drop([center,user_id],axis1,inplaceTrue) locations 3 加载几何形状 使用…

27 - 数据传送指令

---- 整理自B站UP主 踌躇月光 的视频 文章目录 1. CPU 电路2. 数据传送指令的几种情况3. 实验工程4. 实验结果 1. CPU 电路 2. 数据传送指令的几种情况 # program.asm; 1. ; MOV A, 5;; 2. ; MOV A, B;; 3. ; MOV A, [5];; 4. ; MOV B, 6 ; MOV A, [B]; 5. ; MOV [0x2f], 5;; …

Zynq 7000 系列中成功执行BootROM的条件

Zynq 7000设备的启动需要正确的电压序列和I/O引脚控制。BootROM的流程由复位类型、启动模式引脚设置以及启动映像来控制。BootROM对所选启动设备的引脚连接有特定的要求。 Zynq 7000 SoC设备具有电源、时钟和复位要求&#xff0c;这些要求必须得到满足&#xff0c;才能成功执行…

每日OJ题_DFS回溯剪枝⑦_力扣77. 组合

目录 力扣77. 组合 解析代码 力扣77. 组合 77. 组合 难度 中等 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,…

Oracle集群-常用查询及操作(工作日常整理)

1.Oracle集群状态 select * from gv$instance; 示例结果&#xff1a; 2.Oracle集群-增大表空间 常见问题&#xff1a; 导入时或使用时&#xff0c;提示无法extend table ,增加表空间即可 常用操作&#xff1a; 1&#xff09;查询表空间 select * from dba_tablespaces; --…

数据结构——二叉树的顺序存储(堆)(C++实现)

数据结构——二叉树的顺序存储&#xff08;堆&#xff09;&#xff08;C实现&#xff09; 二叉树可以顺序存储的前提堆的定义堆的分类大根堆小根堆 整体结构把握两种调整算法向上调整算法递归版本 非递归版本向下调整算法非递归版本 向上调整算法和向下调整算法的比较 我们接着…

owasp top 10 越权漏洞·

指的是用户权限不明晰。 垂直越权&#xff1a;低权限用户&#xff0c;在无任何身份校验的情况下&#xff0c;能够使用高权 限&#xff08;不属于自己&#xff09;模块&#xff08;功能&#xff09;&#xff0c;或访问高权限拥有的数据&#xff1b; 水平越权&#xff1a;指相同…

华为MRS服务使用记录

背景&#xff1a;公司的业务需求是使用华为的这一套成品来进行开发&#xff0c;使用中发现&#xff0c;这个产品跟原生的Hadoop的那一套的使用&#xff0c;还是有很大的区别的&#xff0c;现记录一下&#xff0c;避免以后忘了 一、原始代码的下载 下载地址&#xff1a;MRS样例…

UVa12313 A Tiny Raytracer

UVa12313 A Tiny Raytracer 题目链接题意分析AC 代码 题目链接 UVA - 12313 A Tiny Raytracer 题意 给出 《训练指南》题意翻译 本题的任务是实现一个小型光线追踪渲染器。场景由若干三角形网格&#xff08;triangle mesh&#xff09;组成&#xff0c;有且仅有一个点光源&…

R语言高级数据管理

一&#xff0c;数学函数 绝对值函数abs(x) sqrt(x) 开平方根 不小于某个数的最小整数ceiling(x) 不大于某个数的最大整数floor(x) 四舍五入round(x) sin(x) cos(x) log(x) 二&#xff0c;统计函数 求平均值 > x<-c(2,3,4,5,6,7,8,9,10) > mean(x) 求和 &g…

RustGUI学习(iced)之小部件(二):如何使用滑动条部件

前言 本专栏是学习Rust的GUI库iced的合集&#xff0c;将介绍iced涉及的各个小部件分别介绍&#xff0c;最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个&#xff0c;目前处于发展中&#xff08;即版本可能会改变&#xff09;&#xff0c;本专栏基于版本0.12.1. 概述…

抓包理解协议

用的Wireshark 抓包 1.抓包网卡选择 - WLAN 无线网卡&#xff0c;其他是本地虚拟机的网卡 这里分别是开始捕获、停止捕获、重新捕获、网卡选择&#xff0c;下面是可以过滤选择 过滤tcp包 3次握手&#xff1a; source是源地址&#xff0c; destination是目标地址&#xff0c;in…

QT文件上传带进度条实例(含源码)

一、Qt上传知识点 QNetworkAccessManager QNetworkAccessManager 是 Qt 中用于执行网络操作的类,它提供了一种方便的方式来发送网络请求并处理响应。以下是关于 QNetworkAccessManager 的一些重要知识点: 发送网络请求:QNetworkAccessManager 可以通过不同的方法发送网络请…