Java全栈经典面试题剖析8】JavaSE高级 -- 线程同步、 线程通信、死锁、线程池

目录

面试题3.44  多线程的同步方式

面试题3.45  多线程安全问题怎么解决

面试题3.46  当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

面试题3.47  简述synchronized与java.util.concurrent.locks.Lock的异同?synchronized和Lock锁两者区别? 谈谈 synchronized和ReentrantLock的区别

面试题3.48  sleep()和wait()有什么区别?

面试题3.49  线程之间是如何通信的?

面试题3.50  为什么wait(),notify()和notifyAll()必须在同步方法或者同步块中被调用?

面试题3.51  线程阻塞有几种情况?遇到阻塞怎么解决?

面试题3.52  如何安全中断运行中的线程?interrupt()方法的作用?

面试题3.53  volatile关键字的作用,能保证线程安全吗

面试题3.54  Java 中 ++ 操作符是线程安全的吗? 

面试题3.55 请说说ThreadLocal?请说说线程本地变量?请说说本地线程?

面试题3.56  死锁的原因

面试题3.57  死锁与活锁的区别,死锁与饥饿的区别?

面试题3.58  java多线程有几种实现方式?你推荐哪一种

面试题3.59  线程池的优点?

面试题3.60  什么是线程池?有哪几种创建方式?四种线程池的创建方式?

面试题3.61  HashMap如何实现线程安全?  ConcurrentHashMap和Hashtable的区别?


面试题3.44  多线程的同步方式

【技术难度:2     出现频率:2  】

1.synchronized修饰的同步代码块;

2.synchronized修饰的同步方法;

3.Lock锁。


面试题3.45  多线程安全问题怎么解决

【技术难度: 2    出现频率:2  】

解决思路是尽量避免多个线程同时操作相同变量。

解决方案有这些:

1.多实例,为每个线程创建一个实例,缺点是浪费空间;

2.添加synchronized关键字,缺点是效率低,逐个线程排队执行;

3.使用本地线程变量ThreadLocal;

4.使用Lock锁,缺点是效率低,逐个线程排队执行;

5.使用局部变量,因为局部变量不存在线程安全的问题,缺点是多线程时不一定具备这种场景。


面试题3.46  当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

【技术难度:2     出现频率:1  】

假设这个线程进入的是该对象的synchronized实例方法,此时其它线程可以进入此对象的其它方法有未加锁的实例方法和类方法,以及synchronized加锁的类方法。


面试题3.47  简述synchronized与java.util.concurrent.locks.Lock的异同?synchronized和Lock锁两者区别? 谈谈 synchronized和ReentrantLock的区别

【技术难度: 2    出现频率:1  】

接下来以实现类ReentrantLock代表Lock锁来回答此问题:

第一层:

1.synchronized是java关键字; Lock是java接口,jdk1.5才出现;

2.synchronized会自动获取或释放锁,Lock锁需要调用lock()或unlock()方法手动获取或释放锁;

3.synchronized如果获取不到锁会一直等待,ReentrantLock如果获取不到锁可以设置时间,超过不等待;

第二层:

4.synchronized是非公平锁,ReentrantLock可以实现公平锁;

5.synchronized只能随机或者全部唤醒,ReentrantLock可以精确或分组唤醒;

6.synchronized锁适合少量代码的同步问题,Lock锁适合大量代码的同步问题。

拓展:

竞争激烈的情况下,Lock锁的性能优于synchronized。竞争不激烈的情况下,synchronized性能好一点,因为synchronized有个锁升级机制,根据竞争激烈程序给锁升级,从偏向锁到轻量级锁再到重量级锁,而到重量级锁的转换需要操作系统帮忙,需要花费较多时间。


面试题3.48  sleep()和wait()有什么区别?

【技术难度:1     出现频率: 1 】

1.sleep()是Thread类的静态方法,wait()是Object类的实例方法;

2.sleep不会释放对象锁,wait会释放对象锁;(会造成锁的二次释放吗?)

3.sleep的休眠时间到达后自动进入就绪状态,wait的线程必须由notify()或notifyAll()唤醒,唤醒后进入同步阻塞状态(重新竞争锁)


面试题3.49  线程之间是如何通信的?

【技术难度:  2   出现频率:1  】

通过Object类的wait()、notify()、notifyAll(),以及Thread类的join()方法,可以进行消息传递,实现让线程等待或唤醒线程,
多线程之间通信是为了避免对同一共享资源的争夺。


面试题3.50  为什么wait(),notify()和notifyAll()必须在同步方法或者同步块中被调用?

【技术难度:  2   出现频率: 1 】

1.调用wait()的线程会释放锁,很显然,先获得锁才能释放锁;

2.notify()、notifyAll()是将锁交给调用了wait()方法的线程,让其继续执行下去,前提是自身获得了锁才能交出锁。


面试题3.51  线程阻塞有几种情况?遇到阻塞怎么解决?

【技术难度: 2    出现频率:2  】

线程阻塞的情况分三种:等待阻塞、同步阻塞、其他阻塞。

三种线程阻塞展开说是这样:

1.等待阻塞是指运行的线程执行了wait()方法,JVM会把该线程放入等待池中;

2.同步阻塞是指运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中;

3.其他阻塞是指运行的线程执行了sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

线程阻塞的解决方法有:

1.sleep()、wait()和join()方法引发的阻塞可以通过interrupt()方法中断;

2.同步锁引发的阻塞可以通过减少锁持有时间,读写锁分离,减小锁的粒度,锁分离,锁粗化等方式来优化锁的性能。

扩展(无需背诵):

阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。


面试题3.52  如何安全中断运行中的线程?interrupt()方法的作用?

【技术难度: 2    出现频率: 1 】

Java Thread 的API里面虽然提供了一个 stop() 方法,可以强行终止线程,但这种方式是不安全的,因为有可能线程的任务还没有完成,突然中断会导致出现运行结果不正确的问题。

因此,在 Thread 里面提供了一个 interrupt() 方法,这个方法要配合isInterrupted()方法来使用,就可以实现安全地中断线程运行。 这种实现方法并不是强制中断,而是告诉正在运行的线程,你可以停止了。何时实际中断,取决于正在运行的线程,所以,它能够保证线程运行结果的安全性。

public class SafeInterruptExample {  public static void main(String[] args) {  Thread worker = new Thread(new RunnableTask());  worker.start();    // 中断工作线程  worker.interrupt();  }  static class RunnableTask implements Runnable {  public void run() {  while (!Thread.currentThread().isInterrupted()) {  // 执行任务  System.out.println("Thread is running...");  }  }  }  
}

面试题3.53  volatile关键字的作用,能保证线程安全吗

【技术难度: 2    出现频率: 1 】

volatile关键字有两个作用,一是可以保证线程获取的数据是最新值(可见性),二是可以防止指令的重排序。它无法保证线程的安全性。

扩展(无需背诵):

当一个共享变量被 volatile 修饰时,它能保证修改的值会立即被更新到主内存,当有其他线程需要读取时,会去主内存中读取新值。


面试题3.54  Java 中 ++ 操作符是线程安全的吗? 

【技术难度:  2   出现频率: 1 】

不是。它涉及到多个指令,如读取变量值,增加,然后存储回内存,并不是原子性的操作,这个过程可能会出现多个线程交差。

一个解决方案是对有i++操作的方法加同步锁。另一个解决方案是使用支持原子操作的类,比如AtomicInteger(java.util.concurrent.atomic.AtomicInteger)。


面试题3.55 请说说ThreadLocal?请说说线程本地变量?请说说本地线程?

【技术难度:  2   出现频率:1  】

第一层:

ThreadLocal可以实现每⼀个线程都有⾃⼰的专属本地变量,创建了⼀个ThreadLocal变量之后,访问这个变量的每个线程都会有这个变量的本地副本。他们可以使⽤get()和set()⽅法来获取或修改当前线程所存的值,从⽽避免线程安全问题。

第二层:

每个线程的本地变量并不是存放在ThreadLocal实例中,而是放在线程对象自己的threadLocals变量中,也就是说,ThreadLocal本地变量是存放在具体的线程空间上,所以不使用本地变量的时候需要调用remove方法删除不用的本地变量(不影响其他线程,否则只要线程不终止那这些不用的变量就会一直存活在线程对象中。


面试题3.56  死锁的原因

【技术难度: 1    出现频率: 1 】

当两个或两个以上的线程(或进程)在执行过程中,互相争夺对方持有的互斥资源,又不释放自己持有的锁资源,造成互相一直等待,此时若无外力作用,它们都将无法推进下去,这就是死锁。


面试题3.57  死锁与活锁的区别,死锁与饥饿的区别?

【技术难度:  3  出现频率:1  】

死锁和活锁的区别在于:处于活锁的线程是在不断的改变状态,就是所谓的“活”,而

处于死锁的线程表现为一直等待,活锁有可能自行解开,死锁则不能

死锁与饥饿的区别在于,死锁除非外力无法解开,饥饿能够被解开,比如当其他高优先级的进程都终止时并且没有更高优先级的进程到达。

死锁、活锁、饥饿基本概念:

1.死锁:是指两个或两个以上的线程(或进程)在执行过程中,因争夺锁资源而造成

的一种互相等待的现象(卡住了),若无外力作用,它们都将无法推进下去。

2.活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,

失败,尝试,失败。

3.饥饿:一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执

行的状态。比如cpu一直给你分到调度。或一直wait,

产生死锁的必要条件:

1.互斥条件:所谓互斥就是进程在某一时间内独占资源。 

2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。

4.等待循环条件:若干进程之间形成一种头尾相接的循环等待资源关系。

Java中导致饥饿的原因:

1.高优先级线程吞噬所有的低优先级线程的 CPU 时间。 

2.线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前

持续地对该同步块进行访问。

3.线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的 wait 方

法),因为其他线程总是被持续地获得唤醒。


面试题3.58  java多线程有几种实现方式?你推荐哪一种

【技术难度:2     出现频率:2  】

有四种,分别是:

1.继承Thread类,重写run()方法;

2.实现Runnable接口,重写run()方法,这种最常用;

3.实现Callable接口,重写call()方法;FutureTask对象的get()方法)

4.线程池。

推荐使用线程池 因为线程池中的线程可以循环使用。


面试题3.59  线程池的优点?

【技术难度:   2  出现频率:2  】

1.可重复使用已有线程;(池化的优点)

2.可有效控制最大并发线程数;

3.提供定时执行、定期执行、单线程、并发数控制等多种功能。


面试题3.60  什么是线程池?有哪几种创建方式?四种线程池的创建方式?

【技术难度: 2    出现频率:2  】

线程池用来管理多个线程,可以先创建好若干线程,使用时直接获取,以空间换时间的方式,提高线程的使用效率。(事先开好,直接从内存中申请,而不需要向系统申请)

线程池创建方式:

  1. Executors.newCachedThreadPool():创建 可以根据需要创建新线程 的线程池,不够创建,用了回收,无限大;
  2. Executors.newFixedThreadPool(n); 创建可重用固定线程数的线程池,如果超过了需要等待;
  3. ScheduledExecutorService ses = Executors.newScheduledThreadPool(n):创建可周期定长线程池,它可延迟运行或周期执行;【延迟操作是子类自己的方法,所以不能用父类对象来引用
  4. Executors.newSingleThreadExecutor() :创建只有一个线程的线程池。

或者创建自定义线程池,根据需求指定线程池参数。


面试题3.61  HashMap如何实现线程安全?  ConcurrentHashMap和Hashtable的区别?

【技术难度:  2   出现频率: 1 】

第一层:

  1. 使用ConcurrentHashMap,它只锁住要修改的部分;
  2. 使用Collections类的synchronizedMap()方法包装一下,这种方式获得的线程安全的HashMap在读写数据的时候会对整个容器上锁,效率低下;
  3. Hashtable读写数据的时候会对整个容器上锁,效率低下。

推荐使用ConcurrentHashMap。

第二层:

ConcurrentHashMap在jdk1.7之前使用分段锁,将数据分段加不同对象锁,jdk1.8开始它用数组中每个头节点作为锁对象来使用synchronized锁,并使用CAS操作来进一步提高效率

扩展(无需背诵):

代码:

Map<Long,Object> map2 = new ConcurrentHashMap<>();

Map<Long,Object> map1 = Collections.synchronizedMap(new HashMap<Long,Object>());

Map<Long, String> map = new Hashtable<>();


------------------------END-------------------------

才疏学浅,谬误难免,欢迎各位批评指正。

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

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

相关文章

联想笔记本电脑睡眠后打开黑屏解决方法

下载联想机器睡眠无法唤醒修复工具 下载地址&#xff1a;https://tools.lenovo.com.cn/exeTools/detail/id/233/rid/6182522.html 使用完后重启电脑&#xff0c;问题解决。

多线程进阶——线程池的实现

什么是池化技术 池化技术是一种资源管理策略&#xff0c;它通过重复利用已存在的资源来减少资源的消耗&#xff0c;从而提高系统的性能和效率。在计算机编程中&#xff0c;池化技术通常用于管理线程、连接、数据库连接等资源。 我们会将可能使用的资源预先创建好&#xff0c;…

亿家旺生鲜云订单零售系统的设计与实现小程序ssm+论文源码调试讲解

2相关技术 2.1微信小程序 小程序是一种新的开放能力&#xff0c;开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。尤其拥抱微信生态圈&#xff0c;让微信小程序更加的如虎添翼&#xff0c;发展迅猛。 2.2 MYSQL数据…

Vue笔记-element ui中关于table的前端分页

对于 Element UI 表格的前端分页&#xff0c;可以在组件中使用 JavaScript 来实现数据的分页显示&#xff0c;而不必从后端获取已分页的数据。以下是一个简单的示例&#xff0c;演示如何在前端进行 Element UI 表格的分页&#xff1a; <template><div><el-tabl…

SpringBoot核心框架之AOP详解

SpringBoot核心框架之AOP详解 一、AOP基础 1. AOP概述 AOP&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程&#xff0c;面向方面编程&#xff09;&#xff0c;其实就是面向特定方法编程。 场景&#xff1a; 项目部分功能运行较慢&#xff0c;定位执行耗时…

CSS_定位_网页布局总结_元素的显示与隐藏

目录 目标 1. 定位 1.1 为什么需要定位 1.2 定位组成 1. 定位模式 2. 边偏移 1.3 静态定位 static&#xff08;了解&#xff09; 1.4 相对定位 relative&#xff08;重要&#xff09; 1.5 绝对定位 absolute&#xff08;重要&#xff09; 1.6 子绝父相的由来&#xff…

【CCL】浅析 CFX Command Language

【CCL】浅析 CFX Command Language 文章目录 【CCL】浅析 CFX Command LanguageI - 前言ActionsPower Syntax II - Perl 语法概述变量定义注释字符串操作符其他 CCL 语法概述参考链接 I - 前言 CCL 全称是 CFX Command Language &#xff0c;是 CFX-Post 软件内部通讯的命令行…

LLM | 论文精读 | NeurIPS 2023 | SWIFTSAGE: 结合快思考与慢思考的生成智能体

论文标题&#xff1a;SWIFTSAGE: A Generative Agent with Fast and Slow Thinking for Complex Interactive Tasks 作者&#xff1a;Bill Yuchen Lin, Yicheng Fu, Karina Yang, Faeze Brahman, Shiyu Huang, Chandra Bhagavatula, Prithviraj Ammanabrolu, Yejin Choi, Xian…

Python的协程与传统的线程相比,是否能更有效地利用计算资源?在多大程度上,这种效率是可测量的?如何量化Python协程的优势|协程|线程|性能优化

目录 1. 协程与线程的基本概念 1.1 线程 1.2 协程 2. 协程的实现原理 2.1 基本示例 3. 协程与线程的效率对比 3.1 资源利用率 3.2 性能测试 4. 使用场景分析 4.1 适用场景 4.2 不适用场景 5. 性能监测与测量 5.1 使用时间记录 5.2 使用第三方库 6. 总结与展望 P…

入门 | Prometheus+Grafana 普罗米修斯

#1024程序员节&#xff5c;征文# 一、prometheus介绍 1、监控系统组成 一个完整的监控系统需要包括如下功能&#xff1a;数据产生、数据采集、数据存储、数据处理、数据展示、分析、告警等。 &#xff08;1&#xff09;、数据来源 数据来源&#xff0c;也就是需要监控的数据…

【认知智能】编译器1

深度学习编译器是一种专门设计用来优化和加速深度学习模型在各种硬件平台上执行的工具。它们通过将高级深度学习框架&#xff08;如TensorFlow, PyTorch等&#xff09;中的计算图转换为针对特定硬件架构优化过的低级代码来实现这一目标。基础架构通常包括以下几个关键组件&…

ML 系列:机器学习和深度学习的深层次总结(17)从样本空间到概率规则概率

一、说明 概率是支撑大部分统计分析的基本概念。从本质上讲&#xff0c;概率提供了一个框架&#xff0c;用于量化不确定性并对未来事件做出明智的预测。无论您是在掷骰子、预测天气还是评估金融市场的风险&#xff0c;概率都是帮助您驾驭不确定性的工具。本篇将讲授概率的原理和…

STM32 第17章 EXIT--外部中断/事件控制器

时间:2024.10.23 参考资料:《零死角玩转STM32》“EXTI-外部中断/事件控制器” STM32里每一个GPIO都能产生中断,中断的产生体现在GPIO的电平的变化,电平的变化需要一个外设来管理,最终传给NVIC(内核里的嵌套中断控制器)来处理。 一、学习内容 1、EXTI功能框图+EXTI初始…

51单片机完全学习——红外遥控

一、红外接收模块原理 红外接收头内部本身有一个反相&#xff0c;意思就是&#xff1a;平时发送方无信号时接收到的是1&#xff0c;发送方有发送载波时接收头引脚输出的是0&#xff0c;写代码的时候注意这一点。红外协议&#xff0c;你也可以理解成&#xff0c;他对0和1重新做…

HarmonyOS 5.0应用开发——Navigation实现页面路由

【高心星出品】 文章目录 Navigation实现页面路由完整的Navigation入口页面子页面 页面跳转路由拦截其他的 Navigation实现页面路由 Navigation&#xff1a;路由导航的根视图容器&#xff0c;一般作为页面&#xff08;Entry&#xff09;的根容器去使用&#xff0c;包括单页面&…

iPhone SE 4:定了

万众期待的iPhone SE 4&#xff0c;近日传来了确定的消息。 近日&#xff0c;屏幕供应链分析师Ross Young透露&#xff1a;iPhone SE 4的屏幕面板&#xff0c;预计在 11 月份开始出货&#xff0c;并将于 2025 年年初正式发布。 来了来了&#xff0c;终于来了。 和以往不同&am…

【C++打怪之路Lv12】-- 模板进阶

#1024程序员节&#xff5c;征文# &#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;重生之我在学Linux&#xff0c;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您…

【jvm】堆的内部结构

目录 1. 说明2. 年轻代&#xff08;Young Generation&#xff09;2.1 说明2.2 Eden区2.3 Survivor区 3. 老年代&#xff08;Old Generation&#xff09;3.1 说明3.2 对象存放3.3 垃圾回收 4. jdk7及之前5. jdk8及之后 1. 说明 1.JVM堆的内部结构主要包括年轻代&#xff08;You…

SpringBoot poi-tl通过模板占位符生成word文件

简介&#xff1a; 开发中我们需要通过在word中使用占位符来动态渲染一些数据&#xff0c;本文讲解poi-tl实现动态生成word文档&#xff0c;包括表格循环&#xff0c;对象嵌套。 poi-tl官网文档 Poi-tl Documentation 1. word格式 这是我的test.word 这是导出后的out.docx文件 …

详解Pectra升级:如何影响以太坊价值及利益相关者

Pectra很可能是最后几个会直接影响用户和ETH持有者的升级之一。 原文&#xff1a;Galaxy Research&#xff1b;编译&#xff1a;Golem&#xff1b;编辑&#xff1a;郝方舟 出品 | Odaily星球日报&#xff08;ID&#xff1a;o-daily&#xff09; 编者按&#xff1a;以太坊 Pectr…