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.mzph.cn/web/56903.shtml

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

相关文章

基于SSM农业信息管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;农业技术管理&#xff0c;种植户管理&#xff0c;农产品类型管理&#xff0c;农资订单管理&#xff0c;系统管理 种植户账号功能包括&#xff1a;系统首页&#xff0c;个人中心&a…

01C++书写hello world、注释、变量、常量

#include <iostream> using namespace std; int main()//main为一个程序的入口&#xff0c;每个程序都必须仅有一个 { cout<<"hello world"<<endl; } //#输出结果为 //单行注释的符号 /* 多行注释的符号 */ //变量创建的语法&#xff1a;数据类…

OpenAI GPT-o1实现方案记录与梳理

本篇文章用于记录从各处收集到的o1复现方案的推测以及介绍 目录 Journey Learning - 上海交通大学NYUMBZUAIGAIRCore IdeaKey QuestionsKey TechnologiesTrainingInference A Tutorial on LLM Reasoning: Relevant methods behind ChatGPT o1 - UCL汪军教授Core Idea先导自回归…

shodan2---清风

注&#xff1a;本文章源于泷羽SEC&#xff0c;如有侵权请联系我&#xff0c;违规必删 学习请认准泷羽SEC学习视频:https://space.bilibili.com/350329294 实验一&#xff1a;search 存在CVE-2019-0708的网络设备 CVE - 2019 - 0708**漏洞&#xff1a;** 该漏洞存在于远程桌面…

offset Explorer连接云服务上的kafka连接不上

以上配置后报连接错误时&#xff0c;可能是因为kafka的server.properties配置文件没配置好&#xff1a; 加上面两条配置&#xff0c;再次测试连接&#xff0c;成功 listeners和advertised.listeners

Xshell远程连接工具详解

Xshell是一款在Windows平台上运行的远程连接工具&#xff0c;它支持SSH1、SSH2以及Microsoft Windows平台的TELNET协议。Xshell通过互联网实现对远程主机的安全连接&#xff0c;帮助用户在复杂的网络环境中享受他们的工作。本文将详细介绍Xshell的溯源、最新版本以及它的优势。…

C++的相关习题(2)

初阶模板 下面有关C中为什么用模板类的原因&#xff0c;描述错误的是? ( &#xff09; A.可用来创建动态增长和减小的数据结构 B.它是类型无关的&#xff0c;因此具有很高的可复用性 C.它运行时检查数据类型&#xff0c;保证了类型安全 D.它是平台无关的&#xff0c;可移植…

springboot连接两个数据源,来回切换数据不能保存? 换事务

springboot连接两个数据源&#xff0c;来回切换数据不能保存&#xff1f; 解决方案 换事务 import org.springframework.transaction.annotation.Transactional; Transactional(propagation Propagation.REQUIRED, isolation Isolation.READ_COMMITTED)换为 import com.ba…

Vue.js 组件开发教程:从基础到进阶

Vue.js 组件开发教程:从基础到进阶 引言 在现代前端开发中,Vue.js 作为一款流行的 JavaScript 框架,以其简单易用和灵活性赢得了开发者的青睐。Vue 组件是 Vue.js 的核心概念之一,理解组件的开发和使用对构建复杂的用户界面至关重要。本篇文章将详细介绍 Vue.js 组件的开…

NFS练习

一、实验目的 1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 2、开放/nfs/upload目录&#xff0c;为192.168.xxx.0/24网段主机可以上传目录&#xff0c; 并将所有用户及所属的组映射为nfs-upload,其UID和GID均为210 3、将/home/tom目录仅共享给192.168.xxx.xxx这台…

MySQL全文索引检索中文

MySQL全文索引检索中文 5.7.6版本不支持中文检索&#xff0c;需要手动修改配置 ft_min_word_len 1 &#xff0c;因为默认配置 4 SHOW VARIABLES LIKE ft%; show VARIABLES like ngram_token_size;配置 修改 MySQL 配置文件 vim /etc/my.cnf在配置的 [mysqld] 下面添加**ft_…

C++——string的模拟实现(上)

目录 引言 成员变量 1.基本框架 成员函数 1.构造函数和析构函数 2.拷贝构造函数 3.容量操作函数 3.1 有效长度和容量大小 3.2 容量操作 3.3 访问操作 (1)operator[]函数 (2)iterator迭代器 3.4 修改操作 (1)push_back()和append() (2)operator函数 引言 在 C—…

【C++单调栈 贡献法】907. 子数组的最小值之和|1975

本文涉及的基础知识点 C单调栈 LeetCode907. 子数组的最小值之和 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 109 7 。 示例 1&#x…

多eSIM配置文件(MEP)

根据在fediverse上的一个回复&#xff0c;Google Pixel 7和8都应该支持MEP&#xff08;多eSIM配置文件&#xff09;。这一信息在Reddit上的一个帖子中似乎得到了确认&#xff0c;该帖子讨论了eSIM MEP和双eSIM功能。 如果您想进一步研究并检查是否可以通过DIAG&#xff08;诊断…

RabbitMQ是一个开源的消息代理和队列服务器

RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;它基于AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高级消息队列协议&#xff09;协议实现&#xff0c;同时也支持其他消息协议如STOMP、MQTT等。作为一个可靠的消息传递服务&#xff0c;RabbitMQ在分…

NtripShare Cloud平台之CORS服务之基准站RTCM坐标编辑

最近有点累&#xff0c;一直在摸鱼&#xff0c;想在平差方面做点事情&#xff0c;但是一直在构思应该怎么去做&#xff0c;有想法的朋友可以交流。 收到了TW和国内顶尖测绘行业朋友的需求&#xff1a; 1、将NtripShare Cloud的CORS服务模块由单基站模块改为VRS。 2、由于电离…

了解光耦合器输入输出关系---腾恩科技

光耦合器&#xff0c;也称为光隔离器&#xff0c;是电子电路中必不可少的元件&#xff0c;主要用于在隔离部分之间传输信号&#xff0c;同时防止电噪声或高压影响敏感元件。其独特的设计使它们能够在没有直接电接触的情况下&#xff0c;弥合不同电压域之间的差距。在本文中&…

Java基础第四天(实训学习整理资料(四)Java中的方法(函数))

一、定义 方法也叫代码块&#xff0c;用于实现功能代码的封装&#xff0c;方便调用。主要目的是实现代码复用。 二、方法和函数的关系 方法&#xff1a;&#xff08;面向对象&#xff09;在类中定义的成员。&#xff08;成员方法&#xff09;属于类创建出的对象的功能。 函…

Spring Boot驱动的Web版酒店客房管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理酒店客房管理系统的相关信息成为必然。开发…

小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(5)定时器和计数器

越努力&#xff0c;越幸运&#xff01; 兄弟们&#xff0c;要搬家到上海滴水湖了 职业生涯又迎来一次比较重要的变动 郑州->上海->上海临港 哈哈哈 flechazo 小柴冲刺软考中级嵌入式系统设计师系列总目录 一、硬件定时器 从硬件角度来看&#xff0c;定时器&#xf…