互联网Java工程师面试题·Java 并发编程篇·第三弹

news2024/11/26 1:43:39

目录

26、什么是线程组,为什么在 Java 中不推荐使用?

27、为什么使用 Executor 框架比使用应用创建和管理线程好?

27.1  为什么要使用 Executor 线程池框架

27.2  使用 Executor 线程池框架的优点

28、java 中有几种方法可以实现一个线程?

29、如何停止一个正在运行的线程?

30、notify()和 notifyAll()有什么区别?

31、什么是 Daemon 线程?它有什么意义?

32、java 如何实现多线程之间的通讯和协作?

33、什么是可重入锁(ReentrantLock)?

34、当一个线程进入某个对象的一个 synchronized 的实例方法后,其它线程是否可进入此对象的其它方法?

35、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

36、SynchronizedMap 和 ConcurrentHashMap 有什么区别?

37、CopyOnWriteArrayList 可以用于什么应用场景?

38、什么叫线程安全?servlet 是线程安全吗?


26、什么是线程组,为什么在 Java 中不推荐使用?

线程组和线程池是两个不同的概念,他们的作用完全不同,前者是为了方便线程的管理,后者是为了管理线程的生命周期,复用线程,减少创建销毁线程的开销。

27、为什么使用 Executor 框架比使用应用创建和管理线程好?

27.1  为什么要使用 Executor 线程池框架

1 、每次执行任务创建线程 new Thread() 比较消耗性能,创建一个线程是比较耗时、耗资源的。
2 、调用 new Thread() 创建的线程缺乏管理,被称为野线程,而且可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪,还有线程之间的频繁交替也会消耗很多系统资源。
3 、直接使用 new Thread() 启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不便实现。

27.2  使用 Executor 线程池框架的优点

1 、能复用已存在并空闲的线程从而减少线程对象的创建从而减少了消亡线程的开销。
2 、可有效控制最大并发线程数,提高系统资源使用率,同时避免过多资源竞争。
3 、框架中已经有定时、定期、单线程、并发数控制等功能。
综上所述使用线程池框架 Executor 能更好的管理线程、提供系统资源使用率。

28java 中有几种方法可以实现一个线程?

继承 Thread
实现 Runnable 接口
实现 Callable 接口,需要实现的是 call() 方法

29、如何停止一个正在运行的线程?

使用共享变量的方式
在这种方式中,之所以引入共享变量,是因为该变量可以被多个执行相同任务的线程用来作为是否中断的信号,通知中断线程的执行。
使用 interrupt 方法终止线程
如果一个线程由于等待某些事件的发生而被阻塞,又该怎样停止该线程呢?这种情况经常会发生,比如当一个线程由于需要等候键盘输入而被阻塞,或者调用Thread.join()方法,或者 Thread.sleep() 方法,在网络中调用ServerSocket.accept()方法,或者调用了 DatagramSocket.receive() 方法时,都有可能导致线程阻塞,使线程处于处于不可运行状态时,即使主程序中将该线程的共享变量设置为 true ,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这里我们给出的建议是,不要使用 stop() 方法,而是使用 Thread 提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码。

30notify()notifyAll()有什么区别?

当一个线程进入 wait 之后,就必须等其他线程 notify/notifyall, 使用 notifyall, 可以唤醒所有处于 wait 状态的线程,使其重新进入锁的争夺队列中,而 notify 只能唤醒一个。
如果没把握,建议 notifyAll ,防止 notigy 因为信号丢失而造成程序异常。

31、什么是 Daemon 线程?它有什么意义?

所谓后台 (daemon) 线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说, 只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用 setDaemon()方法,才能把它设置为后台线程。注意:后台进程在不执行 finally子句的情况下就会终止其 run() 方法。
比如: JVM 的垃圾回收线程就是 Daemon 线程, Finalizer 也是守护线程。

32java 如何实现多线程之间的通讯和协作?

中断 和 共享变量

33、什么是可重入锁(ReentrantLock)?

举例来说明锁的可重入性
public class UnReentrant
{
    Lock lock = new Lock();
    public void outer()
    {
     lock.lock();
     inner();
     lock.unlock();
    }
    public void inner()
    {
     lock.lock();
     //do something
     lock.unlock();
    }
}
outer 中调用了 inner outer 先锁住了 lock ,这样 inner 就不能再获取 lock 。其实调用 outer 的线程已经获取了 lock 锁,但是不能在 inner 中重复利用已经获取的锁资源,这种锁即称之为 不可重入可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。
synchronized ReentrantLock 都是可重入的锁,可重入锁相对来说简化了并发编程的开发。

34、当一个线程进入某个对象的一个 synchronized 的实例方法后,其它线程是否可进入此对象的其它方法?

如果其他方法没有 synchronized 的话,其他线程是可以进入的。
所以要开放一个线程安全的对象时,得保证每个方法都是线程安全的。

35、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

悲观锁 :总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比如 Java 里面的同步原语 synchronized 关键字的实现也是悲观锁。
乐观锁 :顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于 write_condition 机制,其实都是提供的乐观锁。在 Java中 java.util.concurrent.atomic 包下面的原子变量类就是使用了乐观锁的一种实现方式 CAS 实现的。
乐观锁的实现方式:
1 、使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时可以采取丢弃和再次尝试的策略。
2 java 中的 Compare and Swap CAS ,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。 CAS 操作中包含三个操作数 —— 需要读写的内存位置( V )、进行比较的预期原值( A )和拟写入的新值(B) 。如果内存位置 V 的值与预期原值 A 相匹配,那么处理器会自动将该位置值更新为新值 B 。否则处理器不做任何操作。
CAS 缺点:
1 ABA 问题:
比如说一个线程 one 从内存位置 V 中取出 A ,这时候另一个线程 two 也从内存中取出 A ,并且 two 进行了一些操作变成了 B ,然后 two 又将 V 位置的数据变成 A ,这时候线程 one 进行 CAS 操作发现内存中仍然是 A ,然后 one 操作成功。尽管线程 one CAS 操作成功,但可能存在潜藏的问题。从 Java1.5 开始 JDK atomic包里提供了一个类 AtomicStampedReference 来解决 ABA 问题。
2 、循环时间长开销大:
对于资源竞争严重(线程冲突严重)的情况, CAS 自旋的概率会比较大,从而浪费更多的 CPU 资源,效率低于 synchronized
3 、只能保证一个共享变量的原子操作:
当对一个共享变量执行操作时,我们可以使用循环 CAS 的方式来保证原子操作,但是对多个共享变量操作时,循环 CAS 就无法保证操作的原子性,这个时候就可以用锁。

36SynchronizedMap ConcurrentHashMap 有什么区别?

SynchronizedMap 一次锁住整张表来保证线程安全,所以每次只能有一个线程来访为 map
ConcurrentHashMap 使用分段锁来保证在多线程下的性能。
ConcurrentHashMap 中则是一次锁住一个桶。 ConcurrentHashMap 默认将hash 表分为 16 个桶,诸如 get,put,remove 等常用操作只锁当前需要用到的桶。 这样,原来只能一个线程进入,现在却能同时有 16 个写线程执行,并发性能的提升是显而易见的。
另外 ConcurrentHashMap 使用了一种不同的迭代方式。在这种迭代方式中,当iterator 被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时 new 新的数据从而不影响原有的数据 ,iterator 完成后再将头指针替换为新的数据 ,这样 iterator 线程可以使用原来老的数据,而写线程也可以并发的完成改变。

37CopyOnWriteArrayList 可以用于什么应用场景?

CopyOnWriteArrayList( 免锁容器 ) 的好处之一是当多个迭代器同时遍历和修改这个列表时,不会抛出 ConcurrentModificationException 。在CopyOnWriteArrayList 中,写入将导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行。
1 、由于写操作的时候,需要拷贝数组,会消耗内存,如果原数组的内容比较多的情况下,可能导致 young gc 或者 full gc
2 、不能用于实时读的场景,像拷贝数组、新增元素都需要时间,所以调用一个 set操作后,读取到数据可能还是旧的, 虽然 CopyOnWriteArrayList 能做到最终一致性, 但是还是没法满足实时性要求;
CopyOnWriteArrayList 透露的思想
1 、读写分离,读和写分开
2 、最终一致性
3 、使用另外开辟空间的思路,来解决并发冲突

38、什么叫线程安全?servlet 是线程安全吗?

线程安全是编程中的术语,指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。
Servlet 不是线程安全的, servlet 是单实例多线程的,当多个线程同时访问同一个方法,是不能保证共享变量的线程安全性的。
Struts2 action 是多实例多线程的,是线程安全的,每个请求过来都会 new 一个新的 action 分配给这个请求,请求完成后销毁。
SpringMVC Controller 是线程安全的吗?不是的,和 Servlet 类似的处理流程。
Struts2 好处是不用考虑线程安全问题; Servlet SpringMVC 需要考虑线程安全问题,但是性能可以提升不用处理太多的 gc ,可以使用 ThreadLocal 来处理多线程的问题。

要想了解更多:

千题千解·Java面试宝典_时光の尘的博客-CSDN博客

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

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

相关文章

天猫用户重复购买预测(速通二)

天猫用户重复购买预测(二) 模型训练分类相关模型1、逻辑回归分类模型2、K近邻分类模型3、高斯贝叶斯分类模型4、决策树分类模型5、集成学习分类模型 模型验证模型验证指标 特征优化特征选择技巧1、搜索算法2、特征选择方法 模型训练 分类相关模型 1、逻…

基于Springboot实现商务安全邮箱邮件收发系统项目【项目源码+论文说明】

基于Springboot实现商务安全邮箱邮件收发系统演示 摘要 随着社会的发展,社会的方方面面都在利用信息化时代的优势。计算机的优势和普及使得商务安全邮箱的开发成为必需。 本文以实际运用为开发背景,运用软件工程原理和开发方法,采用jsp技术…

Altium Designer | 5 - 网表导入及模块化布局设计(待续)

导入常见报错解决办法(unknow pin及绿色报错等) 在原理图界面 CtrlF搜索元器件位号 在PCB界面,CtrlF是左右翻转, 快捷键JC才是搜索元器件位号 报错信息: Unknow pin 1.没有封装 2.封装管脚缺失 3.元件库对应的管脚不对 ... 常见绿色报…

一键部署开源AI(人工智能对话模型)(支持显卡或CPU加内存运行)--ChatGLM2-6B

一、基本介绍: ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上,ChatGLM2-6B 引入了如下新特性: 更强大的性能: 基于 ChatGLM 初代模…

盘点15个前端开源项目,yyds!

目录 1、vue-color-avatar2、Reader3、Ant Design4、小游戏2048(Vue版)5、跳一跳6、lifeRestart(人生重开模拟器)7、GOVIEW8、vlife9、网易云音乐 API10、饿了么11、QQ音乐 API12、ChatGPT API13、Node.js 最佳实践14、Awesome No…

云计算革命:多云管理与混合云的实践指南

文章目录 云计算的演进多云管理的优势1. 降低风险2. 提高性能3. 降低成本4. 提高安全性 实践指南1. 选择适当的云提供商2. 使用云管理平台3. 实施一致的安全策略4. 数据管理和迁移5. 自动化和编排 混合云的实践1. 私有云和本地数据中心2. 数据一致性3. 安全性和合规性4. 负载均…

IDEA启动报错Failed to create JVM. JVM path的解决办法

今天启动IDEA时IDEA报错,提示如下。 if you already hava a JDK installed, define a JAVA_HOME variable in Computer > Systen Properties > System Settings > Environment Variables.Failed to create JVM. JVM path:D:\ideaIU2023.2.3\IntelliJ IDE…

表单页面风格如何选择?弹窗 or 抽屉 or 页面?

一、类型介绍 在 PC 端项目中,用户触发了某个操作,当需要向用户展示新的内容时,有很多交互方式,弹窗、抽屉、页面就是其中典型的3种。下面来分析下3种交互方式的优势、劣势和使用场景。 1.1 弹窗 定义:分为模态和非模态对话框2种,常用的为模态对话框。 优势:在不离开…

AI项目十六:YOLOP 训练+测试+模型评估

若该文为原创文章,转载请注明原文出处。 通过正点原子的ATK-3568了解到了YOLOP,这里记录下训练及测试及在onnxruntime部署的过程。 步骤:训练->测试->转成onnx->onnxruntime部署测试 一、前言 YOLOP是华中科技大学研究团队在2021年…

2023软件测试面试题(亲身经历)

在职,5年测试经验,坐标广州,有点想666。于是进行了几场线上面试… 1、python有哪些数据类型 数字型:int/float/bool/complex 字符串:str 列表:list 元组:tuple 字典:dict 集合&…

云原生应用安全性:解锁云上数据的保护之道

文章目录 云原生应用的崛起云原生应用安全性挑战1. **容器安全性**:容器技术如Docker和Kubernetes已成为云原生应用的核心组成部分。容器的安全性变得至关重要,以防止恶意容器的运行和敏感数据泄漏。2. **微服务安全性**:微服务架构引入了多个…

从零开始使用webpack搭建一个react项目

先做一个正常编译es6语法的webpack demo 1. 初始化package.json文件 npm init一路enter下去 2. 添加插件 {"name": "demo","version": "1.0.0","description": "","main": "index.js",&q…

Springboot利用CompletableFuture异步执行线程(有回调和无回调)

目录 背景 实现 一、异步线程配置类 二、自定义异步异常统一处理类 三、实现调用异步(无回调-runAsync()) 四、实现调用异步(有回调-supplyAsync()) 五、异步执行错误异常示例 背景 项目中总会有需要异步执行来避免浪费…

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理 第一步: 在已经安装好的tomcat的bin目录下: 输入cmd,进入命令窗口 安装服务: 输入如下命令,最后是你的服务名,避免中文和特殊字符 service.…

Redis数据类型及命令

目录 (一)通用命令(二)String类型(三)Hash类型(四)List类型(五)Set类型(六)SortedSet类型 在redis命令行查询redis通用命令&#xff1…

如何使用摩尔信使MThings连接网络设备

帽子: 摩尔信使MThings支持Modbus-TCP、Modbus-RTU Over TCP、Modbus-TCP Over UDP、Modbus-RTU Over UDP。 TCP链接中,摩尔信使MThings支持灵活的连接方式,主机可作为客户端也可以作为服务端,同时支持模拟从机以客户端方式向远…

1600*C. Add One(数位DP找规律)

Problem - 1513C - Codeforces 解析: 考虑DP,DP[ i ] 为从 0 开始执行 i 次操作,此时数字的位数。 我们发现当一个9再操作一次就会变成1和0,并且相邻的大部分长度都不会变化,0会影响10次操作之后的位数,1会…

开源自动化测试框架优缺点对比

1. Robot Framework Robot Framework(RF)是用于验收测试和验收测试驱动开发(ATDD)的自动化测试框架。 基于 Python 编写,但也可以在 Jython(Java)和 IronPython(.NET) 上…

网页版微信CRM系统,让微信管理更方便!

微信,作为现在热门的社交软件之一,已经成为商家和消费者交流的主要渠道。但对于客服这类人群来说,一个得管理多个微信号,耗费了他们大量时间精力。 因此,微信CRM 系统应运而生。它可以将多个微信聚合在一个界面中&…

PPO算法逐行代码详解

前言:本文会从理论部分、代码部分、实践部分三方面进行PPO算法的介绍。其中理论部分会介绍PPO算法的推导流程,代码部分会给出PPO算法的各部分的代码以及简略介绍,实践部分则会通过debug代码调试的方式从头到尾的带大家看清楚应用PPO算法在car…