java八股文面试[多线程]——进程与线程的区别

news2024/11/23 7:34:37

定义

1、进程:进程是一个具有独立功能的程序关于某个数据集合的以此运行活动。 是系统进行资源分配和调度的独立单位,也是基本的执行单元。是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动。

进程结构特征: 由程序、数据和进程控制块三部分组成。具有 独立性、并发性、异步性和动态性的特点。

(1)、进程的概念主要有两点:

第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括

文本区域(text region)--存储处理器执行的代码,

数据区域(data region)--存储程序执行期间的一些数据变量,

堆栈(stack region)--存储动态分配的内存和本地变量及指令。

第二:进程是一个“执行中的程序”。程序是一个没有生命的实体,只有在运行时处理器才会赋予它生命,才能成为一个活动的实体,我们称其为“进程”。

每一个进程都会有一个独一无二的编号,被称为进程标识码,简称PID(Process,identifier),它是一个取值为1-32768.但是init是一个特殊的进程。所谓的init进程,是一个内核启动的用户级进程,也是系统上运行的所有其他进程的父进程,他会观察子进程,并在需要的时候启动,停止,重新启动它们,init进程主要完成系统各项的配置。linux系统中,init从根文件夹系统目录里的/etc/inittab文件里获取信息。是所有进程的发起者和控制者,内核启动后,便由init进程来进行各项配置。

(2)、进程的三种状态:

就绪(Ready)状态:当进程分配到除CPU以外的必要资源后,只要再获得CPU,便可以立即执行,进程这时的状态为就绪状态。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列

阻塞(Blocked)状态:正在执行的进程由于发生某事件或接受某消息无法继续执行时,便放弃处理机而处于暂停状态,也即进程的执行收到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态和封锁状态。通常使进程处于阻塞的原因有:请求I/O,申请缓冲空间。也会产生一个相应的阻塞队列。

运行(Running)状态:进程已获得CPU,其程序正在执行。在单处理机系统中,只有一个进程处于执行状态,在多处理机系统中,则有多个进程处于执行状态;

其关系如下图所示:

2、线程:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源( 程序计数器,一组寄存器和栈),但它可与同属一个进程的其他线程 共享进程所拥有的全部资源。

线程优点:

  • (1)易于调度。
  • (2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一个程序的不同部分。
  • (3)开销少。创建线程比创建进程要快,所需开销少,占用的资源也少;
  • (4)充分发挥多处理器的功能。通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分的运行。

二、进程与线程的区别

(1)调度:线程作为处理器调度分配的基本单位,而进程是作为拥有资源的基本单位

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行

(3)拥有资源:进程是拥有资源的一个独立单位,有自己独立的地址空间;线程不拥有系统资源,但可以访问隶属于进程的资源,共享进程的地址空间.

(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

三、进程和线程的关系

(1)二者均可并发执行.

(2)线程是指进程内的一个执行单元,也是进程内的可调度实体。一个程序至少有一个进程,一个进程至少有一个线程,一个线程只属于一个进程.

(3)资源分配给进程,同一进程的所有线程共享该进程的所有资源。

(4)处理机分给线程,即真正在处理机上运行的是线程。

(5)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。而线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

四、进程间通信的方式

(1)管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。

(2)信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。

(3)消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限的进程则可以从消息队列中读取信息。

(4)共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。

(5)信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间的同步和互斥手段。

(6)套接字(socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

多线程的优缺点

优点

  • 能适当提高程序的执行效率
  • 能适当提高资源的利用率(CPU,内存)
  • 线程上的任务执行完成后,线程会自动销毁

缺点

  • 开启线程需要占用一定的内存空间(默认情况下,每一个线程都占 512 KB
  • 如果开启大量的线程,会占用大量的内存空间,降低程序的性能
  • 线程越多,CPU 在调用线程上的开销就越大
  • 程序设计更加复杂,比如线程间的通信、多线程的数据共享

多线程使用场景:

场景1:当某个接口响应速度很慢的时候,可以使用多线程提升响应速度。前提是这个接口获取信息的逻辑互相独立,比如首页接口,需要获取列表A,列表B,列表C等,而列表ABC三者之间互相独立(也就是不需要获取到A,就能获取到B),互相之间没有关系。这种情况就可以使用多线程去优化,总耗时为获取3个列表当中耗时最长的那个。

场景2:多线程分批次处理集合数据,不处理重复的数据。比如有一张学生表,数据量很大,你需要根据表当中的姓名和身份证号这两个字段去调用外部接口(外部接口一次只能校验一条数据),校验之后还需要更新这张表。这个时候可以使用多线程分批次处理,大大提高效率。

public class TestApp {

    //配置需要同时开启多少个线程进行处理
    private final int threadNum = 10;

    /**
     * @param list 要处理的集合数据,如果查询较慢,可以多线程分批次查询然后汇总在一块
     */
    public void handleData(List<User> list)  {
        int size = list.size();
        if (size == 0 || list == null) {
            return;
        }
        ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
        List<Future<List<User>>> futures = new ArrayList<Future<List<User>>>(size);
        for (int i = 0; i < threadNum; i++) {
            //将数据分成threadNum份,线程同时执行
            int from = size / threadNum * i;
            int to = size / threadNum * (i + 1);
            if (i == threadNum - 1) {
                to = size;
            }
            List<User> subList = list.subList(from, to);
            Callable<List<User>> task = new Callable<List<User>>() {
                @Override
                public List<User> call()  {
                    List<User> list1 = new ArrayList<>();
                    //对每个线程(线程中的每份数据)的逻辑操作
                    for (User user : subList) {
                        //调用外部接口
                        Boolean res = checkNameAndIdCard(user.getName, user.getIdCard);
                        user.setRes(res);
                        list1.add(user);
                    }
                    return list1;
                }
            };
            //添加线程到队列
            futures.add(executorService.submit(task));
        }
        //多线程处理后的集合汇总到all
        List<User> all = new ArrayList<>();
        for (int i = 0; i < futures.size(); i++) {
            try {
                List<User> list1 = futures.get(i).get();
                all.addAll(list1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //批量更新数据库

        executorService.shutdown();
    }


    /**
     * 模拟外部接口
     */
    public Boolean checkNameAndIdCard(String name, String idCard) {
        return true;
    }

}


@Data
class User {
    private Integer id;
    private String name;
    private String idCard;
    private String res;
}

整体流程:
先把要处理的集合从数据库全部捞出来
根据要开的线程数量对集合进行均分
开多线程对每个集合进行处理,处理后返回结果

Future.get()会造成主线程阻塞,也就是当所有future都得到结果后主线程才能继续执行下去

场景3:做异步。比如页面上需要导出excel文件,由于业务要求,需要导出全部数据,导出全部数据大概需要10分钟左右,那如果使用同步的方式,用户需要在这个导出页面等待10分钟,不能做其它操作,这样肯定是不行的。那么可以采用异步,用户点击导出,导出接口主线程往数据库当中插入一条导出记录,开个子线程获取数据,写入Excel文件,完成之后更新导出记录,当中,然后主线程直接给用户返回。这样用户点击导出会生成一个导出记录信息,不用在这里等待,等导出完成,之后可以在导出记录当中进行下载。代码就不贴了。

场景4:监听线程,如果某个线程执行时间过长(可能死循环了),超过了自定义的时间,就把该线程干掉,释放cpu资源

情况1:开一个线程去执行这个任务

public class MainSingle {

    public static final ExecutorService pool = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {

        Runnable runnable = new Runnable() {
            @Override
            public void run()  {
                System.out.println(Thread.currentThread().getName() + "进来了" + this.hashCode());
                try {
                    Thread.sleep(7000);
                } catch (InterruptedException e) {}
            }
        };
        
        FutureTask futureTask = new FutureTask<>(runnable,null);
        pool.submit(futureTask);
        long start = System.currentTimeMillis();
        // 判断是否完成,如果没完成就是一直循环判断
        while (!futureTask.isDone()) {
            long now = System.currentTimeMillis();
            if ((now - start) >= 6000) {//超时时间3000毫秒
                futureTask.cancel(true);
                System.out.println("线程超时了,终止");
            }
        }
        pool.shutdown();
    }

}

情况2:开多个线程,哪个线程死循环,就关闭哪一个线程,不影响其它线程

知识来源:

【23版面试突击】进程和线程的区别,使用线程真的能节省时间?_哔哩哔哩_bilibili

操作系统:进程与线程之间的区别及联系 - 知乎

多线程使用场景_多线程的应用场景_木偶亽~的博客-CSDN博客

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

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

相关文章

W5100S-EVB-PICO主动PING主机IP检测连通性(十)

前言 上一章节我们用我们开发板在UDP组播模式下进行数据回环测试&#xff0c;本章我们用开发板去主动ping主机IP地址来检测与该主机之间网络的连通性。 什么是PING&#xff1f; PING是一种命令&#xff0c; 是用来探测主机到主机之间是否可通信&#xff0c;如果不能ping到某台…

【枚举区间】CF Edu10 C

Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a; 应该反思一下这么典的思路为什么会想不到 枚举区间&#xff0c;一个很经典的套路是&#xff0c;枚举 l&#xff0c;对 r 计数 对于一个l&#xff0c;r取这么多限制中离 l 最近的那个 Code&#xff1a; #inclu…

一分钟科普:如何查看电脑型号?推荐五种常用方法,建议收藏

电脑型号是识别和区分不同电脑设备的关键。无论您是需要升级硬件、安装驱动程序&#xff0c;还是获取技术支持&#xff0c;了解电脑型号都能为您提供有用的信息。以下是几种查看电脑型号的方法&#xff1a; 方法一&#xff0c;物理标签查看法&#xff1a; 许多品牌的电脑在机身…

汽车服务门店小程序模板制作指南

在数字化时代&#xff0c;一个小程序的力量不可忽视。它不仅是展示品牌形象和提供用户服务的重要工具&#xff0c;更是扩大客户群体和提高营收的关键手段。对于汽车服务门店来说&#xff0c;拥有一个精美且功能齐全的小程序&#xff0c;更将成为你在竞争激烈的市场中的重要武器…

pdf文件打开后部分文字无法显示

场景&#xff1a;pdf文件在系统内预览正常&#xff0c;但是下载到本地电脑上&#xff0c;使用wps查看&#xff0c;部分标题会消失&#xff0c;只有标题里面的数字还能显示出来 经过一系列排查&#xff0c;发现查看的电脑上缺失了字体&#xff0c;使用wps查看时&#xff0c;缺失…

公交站牌部分代码

/*** 提交申请*/Log(title "维修业务", businessType BusinessType.UPDATE)PostMapping( "/submitApply/{id}")ResponseBodypublic AjaxResult submitApply(PathVariable Long id ,String variablesStr){try {System.out.println("variables: "…

多个Y轴的echarts图表组件

组件文件&#xff1a;<template><div class"wrap"><div ref"multipleLineChart" :style"{ height: height, width: width }" style"overflow:hidden"></div></div></template><script> exp…

【2D/3D RRT* 算法】使用快速探索随机树进行最佳路径规划(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

java八股文面试[多线程]——阻塞队列

阻塞队列大纲&#xff1a; 什么是阻塞队列 阻塞队列&#xff1a;从名字可以看出&#xff0c;他也是队列的一种&#xff0c;那么他肯定是一个先进先出&#xff08;FIFO&#xff09;的数据结构。与普通队列不同的是&#xff0c;他支持两个附加操作&#xff0c;即阻塞添加和阻塞删…

图像分类学习笔记(七)——MobileNet

一、MobileNetV1 传统的神经网络&#xff0c;内存需求大、运算量大&#xff0c;导致无法在移动设备以及嵌入式设备上运行。之前的VGG16模型权重大小大概有490M&#xff0c;ResNet模型权重大小大概有644M。MobileNet网络是由google团队在2017年提出的&#xff0c;专注于移动端或…

分析三维模型OBJ格式轻量化在网络传输中的重要性

分析三维模型OBJ格式轻量化在网络传输中的重要性 三维模型的OBJ格式轻量化在网络传输中扮演着重要的角色。随着互联网的快速发展和普及&#xff0c;越来越多的三维模型需要通过网络进行传输&#xff0c;涉及到下载、上传、共享等场景。而原始的三维模型文件往往较大&#xff0c…

正中优配:巨头深夜发声:向全社会开放!历史新高,万亿AI龙头火了!

当地时间8月30日周三&#xff0c;美股三大股指团体收涨&#xff0c;接连第四日收高。美股8月买卖进入尾声&#xff0c;出资者重视通胀与工作方面的一些重要经济数据。万亿AI巨子英伟达收涨0.98%&#xff0c;股价再创前史新高。 据百度官方微信大众号8月31日0时音讯&#xff0c…

vue3渲染函数h的简单使用——定义局部组件

vue3渲染函数h的简单使用 基本用法 创建 Vnodes Vue 提供了一个 h() 函数用于创建 vnodes&#xff1a; import { h } from vueconst vnode h(div, // type{ id: foo, class: bar }, // props[/* children */] )更多用法 详情查看官方文档 在SFC中定义局部组件使用 h函数…

【Qt学习】10 利用QSharedMemory实现单例运行

问题 让应用程序只有一个运行实例 QSharedMemory除了可以完成进程间通信&#xff0c;还可以实现应用程序单例化。 解法 首先&#xff0c;看看QSharedMemory的几个函数&#xff1a; 1、QSharedMemory(const QString &key, QObject *parent Q_NULLPTR)构造函数 该构造函数…

Ceph的纠删码特性 EC(Erasure Code)代码流程

从GitHub上Clone Ceph项目&#xff0c;我是基于(ceph version 12.2.11 luminous 版本)的代码来分析的 一、EC&#xff08;Erasure Code&#xff09;是什么&#xff1f; Ceph的纠删码特性EC&#xff1a;将写入的数据分成N份原始数据&#xff0c;通过这N份原始数据计算出M份效验…

html2canvas 截图空白 或出现toDataURL‘ on ‘HTMLCanvasElement或img标签没截下来 的所有解决办法

1.如果截图空白&#xff1a; 1.1以下的参数是必须要有的。 width: shareContent.offsetWidth, //设置canvas尺寸与所截图尺寸相同&#xff0c;防止白边height: shareContent.offsetHeight, //防止白边logging: true,useCORS: true,x:0,y:0,2&#xff0c;如果出现了报错 toData…

go gin gorm连接postgres postgis输出geojson

go gin gorm连接postgres postgis输出geojson 1. 技术环境 go-gin-gorm postgres-postgis 2. 简单实现代码 思路就是&#xff1a;采用原生sql实现查询、更新等&#xff0c;采用gorm的raw来执行sql语句 package mainimport ("fmt""net/http""github.…

23HW-0Day(漏洞检测Tools)V1.7—批量漏洞检测

工具更新一、 更新如下漏洞利用&#xff1a; 1、用友移动管理系统appmanager文件上传 2、用友移动管理系统category文件上传 3、用友U8CRM文件上传 4、用友U8CRM文件读取 5、用友U8-Cloud文件上传 6、致远OAM1移动协同软件命令执行 工具更新二、 本次更新&#xff0c;工具支…

游戏测试和软件测试有什么区别?

针对手游而言&#xff0c;游戏测试的本质是APP&#xff0c;所以不少手游的测试方式与APP测试异曲同工&#xff0c;然而也有所不同。APP更多的是具有一种工具&#xff0c;一款APP好不好用不重要&#xff0c;关键点在于实用。而游戏则具有一种玩具属性&#xff0c;它并不见得实用…

基于mike平原河网水动力学模块建模教程

Mike 11是在河流模拟中应用非常广泛的优秀软件&#xff0c;在洪水演进、实时洪水预报、水库和水工建筑物优化调度、水工建筑物设计、桥梁的水力设计、溃坝过程模拟、河流泥沙输移和河道演变、河流及湿地的生态及水质评估、水污染对流和扩散、突发日常水质污染事故预警方面得到了…