面试(03)————多线程和线程池

一、多线程

1、什么是线程?线程和进程的区别?

2、创建线程有几种方式 ?

3、Runnable 和 Callable 的区别?

4、如何启动一个新线程、调用 start 和 run 方法的区别? 

5、线程有哪几种状态以及各种状态之间的转换? 

6、线程相关的基本方法?

7、 wait()和 sleep()的区别? 

二、线程池 

1、为什么需要线程池

2、线程池的分类(高薪常问) 

 3、核心参数(高薪常问)

4、线程池的原理(高薪常问) 

 5、拒绝策略

6、如何关闭线程池 

7、线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最

大线程?

8、线程池中线程复用原理 


 

一、多线程

1、什么是线程? 线程和进程的区别?

线程:是进程的一个实体,是 cpu 调度和分派的基本单位,是比进程更小的可以独立运行
的基本单位。
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源
分配和调度的一个独立单位。
特点:线性,程的划分尺度小于进程,这使多线程程序拥有高并发进程在运行时各自内存单
元相互独立,线程之间 内存共享,这使多线程编程可以拥有更好的性能和用户体验。

2、创建线程有几种方式 ?

  • 继承 Thread 类并重写 run 方法创建线程,实现简单但不可以继承其他类
  • 实现 Runnable 接口并重写 run 方法。避免了单继承局限性,编程更加灵活,实现 解耦。
  • 实现 Callable 接口并重写 call 方法,创建线程。可以获取线程执行结果的返回值, 并且可以抛出异常。
  • 使用线程池创建(使用 java.util.concurrent.Executor 接口)

038e84216e794ceda286711eaabe1392.png 50dc284ca3624fae8e9efb639adbf158.png

3、Runnable 和 Callable 的区别?

主要区别
Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,支持泛型
Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call
方法允许抛出异常,可以获取异常信息

4、如何启动一个新线程、调用 start 和 run 方法的区别? 

线程对象调用 run 方法不开启线程。仅是对象调用方法。
线程对象调用 start 开启线程,并让 jvm 调用 run 方法在开启的线程中执行
调用 start 方法可以启动线程,并且使得线程进入就绪状态,而 run 方法只是 thread
的一个普通方法,还是在主线程中执行。

5、线程有哪几种状态以及各种状态之间的转换? 

(1)第一是 new-> 新建状态。在生成线程对象, 并没有调用该对象的 start 方法,这
是线程处于创建状态。
(2)第二是 Runnable-> 就绪状态。当 调用了线程对象的 start 方法之后,该线程就
进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状
态。
(3)第三是 Running-> 运行状态。线程调度程序将处于就绪状态的线程 设置为当前线
,此时线程就进入了运行状态, 开始运行 run 函数当中的代码
(4)第四是 阻塞状态。阻塞状态是线程因为某种原因放弃 CPU 使用权,暂时停止运
行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
  • 等待 – 通过调用线程的 wait() 方法,让线程等待某工作的完成。
  • 超时等待 – 通过调用线程的 sleep() 或 join()或发出了 I/O 请求时,线程会进 入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时, 线程重新转入就绪状态。
  • 同步阻塞 – 线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用), 它会进入同步阻塞状态。
(5)第五是 dead-> 死亡状态: 线程执行完了或者因异常退出了 run()方法,该线程结
束生命周期.

 113fe12b8708455b89d4c160cb5e0a7d.png

6、线程相关的基本方法?

  • 线程等待(wait)
    调用该方法的线程进入 WAITING 状态,只有等待另外线程的通知或被中断才会返回, 需要注意的是调用 wait()方法后,会释放对象的锁。因此,wait 方法一般用在同步方法或 同步代码块中。
  • 线程睡眠(sleep)
    sleep 导致当前线程休眠,与 wait 方法不同的是 sleep 不会释放当前占有的 锁,sleep(long)会导致线程进入 TIMED-WATING 状态,而 wait()方法会导致当前线程进 入 WATING 状态.
     
  • 线程让步(yield)
    yield 会使当前线程让出 CPU 执行时间片,与其他线程一起重新竞争 CPU 时间片。 一般情况下,优先级高的线程有更大的可能性成功竞争得到 CPU 时间片,但这又不是绝对 的,有的操作系统对 线程优先级并不敏感。
     
  • 线程中断(interrupt)
    中断一个线程,其本意是给这个线程一个通知信号,会影响这个线程内部的一个中断标 识位。这个线程本身并不会因此而改变状态(如阻塞,终止等)
  • Join 等待其他线程终止
    join() 方法,等待其他线程终止,在当前线程中调用一个线程的 join() 方法,则当前 线程转为阻塞状态,回到另一个线程结束,当前线程再由阻塞状态变为就绪状态,等待 cpu 的宠幸.
  • 线程唤醒(notify)
    Object 类中的 notify() 方法,唤醒在此对象监视器上等待的单个线程,如果所有线 程都在此对象上等待,则会选择唤醒其中一个线程,选择是任意的,并在对实现做出决定 时发生,线程通过调用其中一个 wait() 方法,在对象的监视器上等待,直到当前的线程放 弃此对象上的锁定,才能继续执行被唤醒的线程,被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。类似的方法还有 notifyAll() ,唤醒再次监视器上等 待的所有线程。

7、 wait()和 sleep()的区别? 

(1)来自不同的类
wait():来自 Object 类;
sleep():来自 Thread 类;
(2)关于锁的释放:
wait():在等待的过程中会释放锁;
sleep():在等待的过程中不会释放锁
(3)使用的范围:
wait():必须在同步代码块中使用;
sleep():可以在任何地方使用;
(4)是否需要捕获异常
wait():不需要捕获异常;
sleep():需要捕获异常;

二、线程池 

1、为什么需要线程池

在实际使用中,线程是很占用系统资源的,如果对线程管理不完善的话很容易导致系统问题。
因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好
处:
(1)使用线程池可以重复利用已有的线程继续执行任务,避免线程在创建销毁时造成的消
(2)由于没有线程创建和销毁时的消耗,可以提高系统响应速度
(3)通过线程可以对线程进行合理的管理,根据系统的承受能力调整可运行线程数量的大
小等

2、线程池的分类(高薪常问) 

78864538b7c14d55b1052015b454e1de.png

(1)newCachedThreadPool:创建一个可进行缓存重复利用的线程池
(2)newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列
方式来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量
(3)newSingleThreadExecutor:创建一个使用单个 worker 线程的 Executor ,以无
界队列方式来运行该线程。线程池中最多执行一个线程,之后提交的线程将会排在队列中以
此执行
(4)newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可安排在给
定延迟后运行命令或者定期执行
(5)newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或
者定期的执行
(6)newWorkStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻
最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的 CPU 个数

 3、核心参数(高薪常问)

corePoolSize:核心线程池的大小
maximumPoolSize:线程池能创建线程的最大个数
keepAliveTime:空闲线程存活时间
unit:时间单位,为 keepAliveTime 指定时间单位
workQueue:阻塞队列,用于保存任务的阻塞队列
threadFactory:创建线程的工程类
handler:饱和策略(拒绝策略)

4、线程池的原理(高薪常问) 

e75cdbc795ea48c299cc822752787335.png

线程池的工作过程如下:
当一个任务提交至线程池之后,
(1)线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作
线程来执行任务。否则进入
(2)判断工作队列是否已经满了,倘若还没有满,将线程放入工作队列。否则进入 3.
(3)判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。
如果线程池满了,则交给饱和策略来处理任务。

 5、拒绝策略

ThreadPoolExecutor.AbortPolicy(系统默认):
丢弃任务并抛出RejectedExecutionException 异常,让你感知到任务被拒绝了,我们可以根据业务逻辑选 择重试或者放弃提交等策略。
ThreadPoolExecutor.DiscardPolicy: 也是丢弃任务,但是不抛出异常,相对而言存在
一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执
行任务(重复此过程),通常是存活时间最长的任务,它也存在一定的数据丢失风险。
ThreadPoolExecutor.CallerRunsPolicy:既不抛弃任务也不抛出异常,而是将某些任务
回退到调用者,让调用者去执行它。

6、如何关闭线程池 

关闭线程池,可以通过 shutdownshutdownNow 两个方法
原理:遍历线程池中的所有线程,然后依次中断
1、shutdownNow 首先将线程池的状态设置为 STOP,然后尝试停止所有的正在执行和
未执行任务的线程,并返回等待执行任务的列表;
2、shutdown 只是将线程池的状态设置为 SHUTDOWN 状态,然后中断所有没有正
在执行任务的线程

7、线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最

大线程?

(1)一般的队列只能保证作为一个有限长度的缓冲区,如果超出了缓冲长度,就无法保留当
前的任务了,阻塞队列通过阻塞可以保留住当前想要继续入队的任务。
阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入 wait 状态,
释放 cpu 资源。阻塞队列自带阻塞和唤醒的功能,不需要额外处理,无任务执行时,线程池利用阻塞队列的 take 方法挂起,从而维持核心线程的存活、不至于一直占用 cpu 资源


 
(2)在创建新线程的时候,是要获取全局锁的,这个时候其它的就得阻塞,影响了整体效率。 就好比一个企业里面有 10 个(core)正式工的名额,最多招 10 个正式工,要是任务超过 正式工人数(task > core)的情况下,工厂领导(线程池)不是首先扩招工人,还是这 10
人,但是任务可以稍微积压一下,即先放到队列去(代价低)。10 个正式工慢慢干,迟早
会干完的,要是任务还在继续增加,超过正式工的加班忍耐极限了(队列满了),就的招外
包帮忙了(注意是临时工)要是正式工加上外包还是不能完成任务,那新来的任务就会被领
导拒绝了(线程池的拒绝策略)。

 

8、线程池中线程复用原理 

 

线程池将线程和任务进行解耦,线程是线程,任务是任务,摆脱了之前通过 Thread 创建
线程时的一个线程必须对应一个任务的限制。
在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行,其核心原理在于线程池
对 Thread 进行了封装,并不是每次执行任务都会调用 Thread.start() 来创建新线程,而
是让每个线程去执行一个“循环任务”,在这个“循环任务”中不停检查是否有任务需要被
执行,如果有则直接执行,也就是调用任务中的 run 方法,将 run 方法当成一个普通的
方法执行,通过这种方式只使用固定的线程就将所有任务的 run 方法串联起来。

 

 

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

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

相关文章

极越夏一平反思:论技术我们很能打,要解决品牌认知问题

作者 |张祥威 编辑 |德新 今年起,新能源汽车竞争强度明显再上一个台阶。 华为主导下的问界强势逆袭,雷军亲自坐镇的小米汽车在发布后斩获丰厚的大定订单,给其它汽车品牌带来压力。3月末,在小米发布会前几日,极越在北…

【JavaScript】作用域 ③ ( JavaScript 作用域链 | 作用域链变量查找机制 )

文章目录 一、JavaScript 作用域链1、作用域2、作用域链3、作用域链变量查找机制 二、代码示例 - 作用域链 一、JavaScript 作用域链 1、作用域 在 JavaScript 中 , 任何代码都有 作用域 , 全局作用域 : 在 <script> 标签中 或者 js 脚本中 定义的变量 属于 全局作用域 …

k8s安全控制、授权管理介绍,全网最新

3.ABAC 4.Webhook 5.Node 6.RBAC 三.Role解释 1.Role和ClusterRole 2.Rolebinding和ClusterBinding 3.Rolebinding和ClusterRole 四.准入控制 1.命令格式 2.可配置控制器 五.例子 1.生成签署证书 2.设置用户和上下文信息 3.为sulibao用户授权 一.Kubernetes安全控…

深入剖析主机安全中的零信任机制及其实施原理

引言 在数字化转型加速与云端服务普及的大背景下&#xff0c;传统依赖边界的网络安全模式逐渐显露出其局限性。面对愈发复杂多变的威胁环境&#xff0c;零信任安全架构作为新一代的安全范式应运而生&#xff0c;尤其是在主机层面的安全实践中&#xff0c;零信任机制正扮演着至…

每日OJ题_优先级队列_堆③_力扣692. 前K个高频单词

目录 力扣692. 前K个高频单词 解析代码 力扣692. 前K个高频单词 692. 前K个高频单词 难度 中等 给定一个单词列表 words 和一个整数 k &#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c…

usb_camera传输视频流编码的问题记录!

前言&#xff1a; 大家好&#xff0c;今天给大家分享的内容是&#xff0c;一个vip课程付费的朋友&#xff0c;在学习过程中遇到了一个usb采集的视频数据流&#xff0c;经过ffmpeg编码&#xff0c;出现了问题&#xff1a; 问题分析&#xff1a; 其实这个问题不难&#xff0c;关键…

centos7.2系统部署ZooKeeper集群和Kafka集群(集群应用系统商城前置环境)

本次实验将使用centos7.2系统部署部署ZooKeeper集群因为Kafka依赖于ZooKeeper&#xff0c;所以我们一并进行部署。 实验所示的资源软件已上传至百度网盘&#xff0c;需要自取。 链接&#xff1a;https://pan.baidu.com/s/1a-7_iAIX0DBAMkF9bhiTcA?pwd2333 提取码&#xff1…

泛型(java学习)

目录 1.泛型介绍&#xff1a; 2.泛型的好处&#xff1a; 3.泛型的语法 4.泛型的细节 5.自定义泛型 6.自定义泛型接口 8.泛型的继承和通配符 1.泛型介绍&#xff1a; 1&#xff09;泛型又称参数化类型&#xff0c;解决数据类型的安全性问题。 2&#xff09;在类声明或实例…

[尚硅谷 flink] 基于时间的合流——双流联结(Join)

文章目录 8.1 窗口联结&#xff08;Window Join&#xff09;8.2 **间隔联结&#xff08;Interval Join&#xff09;** 8.1 窗口联结&#xff08;Window Join&#xff09; Flink为基于一段时间的双流合并专门提供了一个窗口联结算子&#xff0c;可以定义时间窗口&#xff0c;并…

实现通讯录(顺序表版本)

一、功能要求 &#xff08;1&#xff09;⾄少能够存储100个⼈的通讯信息 &#xff08;2&#xff09;能够保存⽤⼾信息&#xff1a;名字、性别、年龄、电话、地址等 &#xff08;3&#xff09;增加联系⼈信息 &#xff08;4&#xff09;删除指定联系⼈ &#xff08;5&#…

X年后,ChatGPT会替代底层程序员吗?

能不能替代&#xff0c;真的很难说&#xff0c;因为机器换掉人&#xff0c;这其实是一个伦理问题。 其实说白了&#xff0c;任何行业在未来都会被AI或多或少的冲击到&#xff0c;因为ChatGPT做为一个可以持续提升智能的AI&#xff0c;在某些方面的智能程度超过人类并不是什么难…

数据结构-基本概念

1.什么是数据结构&#xff1f; 数据 数据&#xff0c;是对客观事物的符号表示&#xff0c;在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。 结构 &#xff08;1&#xff09;线性结构&#xff08;比如图书目录文件&#xff0c;一对一的关系&#x…

Unity Meta Quest MR 开发(五):空间锚点

文章目录 &#x1f4d5;教程说明 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量 XR 开发者社区&#xff0c;博主目前在内担任 XR 开发的讲师。该社区提供专人答疑、完整进阶教程、从零到一项目孵化保姆服务&…

文件及相关文件函数的使用

目录 前言 文件的概述 文件类型 如何用C语言来操作文件呢&#xff1f; 文件缓冲区 文件的打开与关闭 文件的打开——fopen&#xff08;&#xff09;函数 文件的关闭——fclose&#xff08;&#xff09;函数 文件结束检测——feof()函数 文件的顺序读写 文件字符输出函…

kubernetes集群添加到jumpserver堡垒机里管理

第一步、在kubernetes集群中获取一个永久的token。 jumpserver堡垒机用api的来管理kubernetes&#xff0c;所以需要kubernetes的token&#xff0c;这个token还需要是一个永久的token&#xff0c;版本变更&#xff1a;Kubernetes 1.24基于安全方面的考虑&#xff08;特性门控Le…

JVM字节码与类的加载——class文件结构

文章目录 1、概述1.1、class文件的跨平台性1.2、编译器分类1.3、透过字节码指令看代码细节 2、虚拟机的基石&#xff1a;class文件2.1、字节码指令2.2、解读字节码方式 3、class文件结构3.1、魔数&#xff1a;class文件的标识3.2、class文件版本号3.3、常量池&#xff1a;存放所…

在 K8s 上跑腾讯云 Serverless 函数,打破传统方式造就新变革

目录 目录 前言 Serverless 和 K8s 的优势 1、关于Serverless 函数的特点 2、K8s 的特点 腾讯云 Serverless 函数在 K8s 上的应用对企业服务的影响 1、弹性扩展和高可用性 2、成本优化和资源利用 3、简化部署和管理 拓展&#xff1a;腾讯云云函数 SCF on K8s 番外篇…

HarmonyOS实战开发-如何实现蓝牙设备发现、配对、取消配对功能。

介绍 蓝牙技术是一种无线数据和语音通信开放的全球规范&#xff0c;它是基于低成本的近距离无线连接&#xff0c;为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。本示例通过ohos.bluetooth 接口实现蓝牙设备发现、配对、取消配对功能。实现效果如下&#xff1a…

计算机网络 实验指导 实验9

实验9 三层交换机综合实验 1.实验拓扑图 名称相连的接口IP地址网关PC1F0/3172.1.1.2/28172.1.1.1/28PC2F0/4172.1.1.18/28172.1.1.17/28PC3F0/5172.1.1.34/28172.1.1.33/28PC4F0/3172.1.1.3/28172.1.1.1/28PC5F0/4172.1.1.19/28172.1.1.17/28PC6F0/5172.1.1.35/28172.1.1.33/2…

ROS 2边学边练(16)-- 自定义msg和srv文件

前言 在前面的文章我们在学习主题&#xff08;topic&#xff09;和服务&#xff08;service&#xff09;通信方法时&#xff0c;使用的一直是ROS 2提供好的消息结构文件&#xff08;xxx.msg&#xff09;和服务结构文件&#xff08;xxx.srv&#xff09;&#xff0c;稀里糊涂的就…