2023年Java核心技术第十篇(篇篇万字精讲)
目录
十九 . 一个线程两次调用start()方法会出现什么情况?线程的生命周期和状态转移。
19.1 典型回答
19.1.1 线程生命周期:
19.1.2 计时等待详细解释:
19.2 深入扩展考察
19.2.1 线程是什么?
19.2.2 Green Thread详细解释:
二十. Java程序产生死锁的情况以及如何进行定位,修复?
20.1 典型回答
20.1.1 定位死锁
20.1.1 .1 详细解释:
十九 . 一个线程两次调用start()方法会出现什么情况?线程的生命周期和状态转移。
线程是Java并发的基础元素。理解,操纵线程是必备技能。
19.1 典型回答
Java线程是不允许启动2次的,第二次调用必然会抛出illegalThreadStateException,运行时异常,多次调用start()被认为编程错误。
19.1.1 线程生命周期:
线程状态被明确定义在其公告内部枚举类型java.lang.Thread.State中:
分别是:
1. 新建(new):
表示线程被创建出来还没有真正启动的状态,可以认为是一个Java内部状态。
2. 就绪(runnable):
表示该线程已经在JVM中执行,当然由于执行需要计算资源,它可能是正在运行,也可能是还在等待系统分配给它CPU片段,在就绪队列里面排队。
3. 阻塞(blocked)
状态和讲的同步相关,阻塞表示线程在等待Monitor lock 。
如:
线程试图通过synchronized去获取某个锁,但是其他线程已经独占了,就会导致阻塞问题,使得线程处于阻塞状态。
4. 等待(waiting)
表示正在等待其他线程采取某些操作,
场景:类似生产者消费者模式,发现任务条件并没有满足,会让当前消费者线程等待(wait),另外的生产者线程去准备任务数据,然后通过类似notify等动作,通知消费者继续工作。
Thread.join()也会令线程进入等待状态。
5. 计时等待(timed_wait)
进入条件和等待状态类似,但是调用的是存在超时条件方法,比如wait或join等方法的指定超时版本。
6. 终止(terminated):
不管是意外退出还是正常执行结束,线程已经完成使命,终止运行。
当我们进行第二次调用start()方法的时候,线程可能处于终止或者其他(非new)状态,但是无论如何,都是不可以再次启动的。
19.1.2 计时等待详细解释:
当一个线程等待其他线程完成某个任务,并设置了超时时间,可以使用timed_wait方法。
public class TimedWaitExample {private boolean isTaskComplete = false;public synchronized void waitForTask() {try {// 设置等待超时时间为5秒wait(5000);if (!isTaskComplete) {System.out.println("任务未能在指定时间内完成,继续执行其他操作");}} catch (InterruptedException e) {e.printStackTrace();}}public synchronized void completeTask() {// 模拟任务完成try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}isTaskComplete = true;notifyAll();}public static void main(String[] args) {TimedWaitExample example = new TimedWaitExample();// 创建等待任务的线程Thread waitThread = new Thread(() -> {example.waitForTask();});// 创建完成任务的线程Thread completeThread = new Thread(() -> {example.completeTask();});// 启动线程waitThread.start();completeThread.start();try {// 等待两个线程执行完成waitThread.join();completeThread.join();} catch (InterruptedException e) {e.printStackTrace();}}
}
TimedWaitExample
类包含了一个waitForTask
方法和一个completeTask
方法。在waitForTask
方法中,调用了带有超时参数的wait
方法,等待任务完成或超过5秒的时间限制。在completeTask
方法中,模拟了任务的完成,并通过notifyAll
方法唤醒处于等待状态的线程。
在main
方法中,创建了一个等待任务的线程和一个完成任务的线程,并启动它们。然后,使用join
方法等待两个线程执行完成。
如果完成任务的线程在5秒内完成了任务,则等待线程会被唤醒并继续执行。如果任务未能在指定时间内完成,等待线程会输出一条提示信息并继续执行其他操作。
例子展示了如何使用timed_wait方法来实现线程等待超时的功能。
19.2 深入扩展考察
面试热身题,进行对基本状态的简单的流转进行介绍,对线程进行理解是对我们日常开发和诊断分析有很大的帮助,都是必备的基础。
作为突破口,进行从各个不同的角度考察你对线程的掌握。
19.2.1 线程是什么?
操作系统的角度,我们可以简单的认为,线程是系统调度的最小单元,一个进程可以包含多个线程,作为任务真正运作者,有自己的栈(Stack),寄存器(Register),本地存储(Thread Local)等,但是会和进程内其他线程共享描述符,虚拟地址空间等。
具体实现中,线程分为内核线程,用户线程,Java的线程实现其实是与虚拟机相关的。
对于我们最熟悉的JDk,线程也进行了一个演进过程,基本上在Java 1.2 后,JDK已经抛弃了Green Thread,也就是用户调度的线程,现在的模型是一对一映射到操作系统内核线程。
19.2.2 Green Thread详细解释:
Green Thread模型的设计初衷是为了使Java程序能够在不依赖底层操作系统的情况下运行,并具备跨平台的能力。在Green Thread模型中,Java虚拟机自己实现了对线程的调度和管理,而不是依赖于底层操作系统的线程支持。
然而,由于Green Thread模型没有直接与操作系统内核进行交互,因此导致了一些限制和问题:
-
无法充分利用多核处理器的性能:由于Green Thread模型的线程调度和管理是由Java虚拟机自己完成的,它无法直接利用多核处理器的并行计算能力。在这种模型下,即使在具有多个物理核心的处理器上运行Java程序,所有的线程仍然只能通过单个物理核心来执行,不能实现真正的并行计算。
-
无法与底层操作系统进行充分的集成:Green Thread模型无法直接与底层操作系统进行交互,因此无法充分利用操作系统提供的各种线程调度算法和特性。
-
对资源的占用较大:由于Green Thread模型需要自己实现线程调度和管理,它需要占用较多的内存资源。每个Green Thread都需要分配一定的堆栈空间,而且它们的调度算法和状态维护也需要一定的计算和存储开销。
为了克服这些限制和问题,从Java 1.2版本开始,JDK采用了一对一映射到操作系统内核线程的模型,也称为"native thread"模型。这种模型能够更好地利用多核处理器的性能,并与底层操作系统进行充分的集成,提供更高效和可靠的线程支持。
Green Thread模型在提供跨平台能力方面具有优势,但无法充分利用多核处理器并与底层操作系统进行充分的集成。因此,JDK在Java 1.2之后放弃了Green Thread模型,转而使用一对一映射到操作系统内核线程的模型,以提供更强大和高效的线程支持。
二十. Java程序产生死锁的情况以及如何进行定位,修复?
20.1 典型回答
死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待中,没有任何个体可以继续前进。
死锁不仅仅是在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。
通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,
20.1.1 定位死锁
定位死锁最常见的方式就是利用jstack工具获取线程栈,然后定位互相之间的依赖关系,进而找到死锁,如果是明细的死锁,我们可以通过jstack进行定位。
程序运行发生死锁后,绝大多数情况,无法在线进行解决,只能进行重启,修正程序本身的问题。
20.1.1 .1 详细解释:
当程序发生死锁时,通常情况下无法立即在运行时解决它,因为死锁是由于线程之间的资源竞争导致的相互等待,形成了一个循环依赖的状态。
死锁通常发生在多个线程同时请求一组共享资源,并且每个线程都持有一部分资源并等待其他线程释放它们所需的资源。当发生这种情况时,没有任何一个线程能够继续执行下去,它们被阻塞在等待资源释放的状态中,从而导致程序无法继续正常执行。
解决死锁问题需要针对程序本身进行修正,以消除或避免死锁的产生。以下是一些常见的方法:
-
分析和检测死锁:使用工具或技术来分析和检测死锁。例如,通过线程转储分析工具(如jstack)、死锁检测工具(如Java自带的jconsole、VisualVM或第三方工具)来查看线程的状态和死锁信息。
-
梳理锁的获取顺序:确保线程获取锁的顺序是一致的,避免出现循环依赖的情况。例如,如果线程A先获取锁1,再获取锁2,那么其他线程也应该按照相同的顺序获取这两个锁。这种预防措施可以减少死锁的发生。
-
避免长时间持有锁:尽量减少在持有锁的情况下进行耗时的操作,比如I/O操作或者远程调用。可以使用异步操作或者将操作拆分为更小的单元,以便在持有锁期间减少执行时间。
-
使用超时机制:在获取锁时设置一个超时时间,在等待超过一定时间后放弃获取锁并采取相应的处理策略。这可以避免线程无限期地等待锁而导致死锁。
-
死锁恢复策略:当检测到死锁时,程序可以采取恢复策略,例如释放已经获得的锁并回退一些操作,然后重新尝试执行。这个策略需要根据具体的业务场景来设计和实现。
尽管有以上的方法来预防和解决死锁问题,但有时候死锁发生的原因非常复杂,可能需要对程序进行彻底的重构才能解决。在这种情况下,重新启动程序是一种常见的解决方法,因为它可以清除死锁并重新开始执行。
总结起来,当程序发生死锁时,无法在线进行解决的大多数情况下需要重启程序,并通过修正程序本身的问题来避免死锁的再次发生。这涉及到分析和检测死锁、优化锁的获取顺序、避免长时间持有锁、使用超时机制以及实施死锁恢复策略等方法。
相关文章:

2023年Java核心技术第十篇(篇篇万字精讲)
目录 十九 . 一个线程两次调用start()方法会出现什么情况?线程的生命周期和状态转移。 19.1 典型回答 19.1.1 线程生命周期: 19.1.2 计时等待详细解释: 19.2 深入扩展考察 19.2.1 线程是什么? 19.2.2 Green…...

分享一篇关于如何使用BootstrapVue的入门指南
你想轻松地创建令人惊叹且响应式的在线应用程序吗?使用BootstrapVue,您可以快速创建美观且用户友好的界面。这个开源工具包是基于Vue.js和Bootstrap构建的,非常适合开发现代Web应用程序。本文将介绍其基础知识,让您可以开始使用这…...

【1day】复现Cellular Router命令执行漏洞
目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 移动路由器(Cellular Router)是一种利用移动网络提供无线互联网连接的设备。它们类似于传统路由器,但不同于使用有线连接(如以太网或DSL)...

【Torch API】pytorch 中repeat_interleave函数详解
torch.repeat_interleave(input, repeats, dimNone) → Tensor Repeat elements of a tensor. Parameters input (Tensor) – the input tensor. repeats (Tensor or int) – The number of repetitions for each element. repeats is broadcasted to fit the shape of the …...

TDesign表单rules通过函数 实现复杂逻辑验证输入内容
Element ui 中 我们可以通过validator 绑定函数来验证一些不在表单model中的值 又或者处理一下比较复杂的判断逻辑 TDesign也有validator 但比较直观的说 没有Element那么好用 这里 我们给validator绑定了我们自己的checkAge函数 这个函数中 只有一个参数 value 而且 如果你的…...

springgateway网关修改响应后,部分中文乱码问题
原因 是因为响应体过大,开启了压缩,数据分段进行响应得,导致处理返回体得时候乱码 解决方式 Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request exchange.getR…...

微信开发之一键发布群公告的技术实现
简要描述: 设置群公告 请求URL: http://域名地址/setChatRoomAnnouncement 请求方式: POST 请求头Headers: Content-Type:application/jsonAuthorization:login接口返回 参数: 参数名必…...

R语言和Python用泊松过程扩展:霍克斯过程Hawkes Processes分析比特币交易数据订单到达自激过程时间序列...
全文下载链接:http://tecdat.cn/?p25880 本文描述了一个模型,该模型解释了交易的聚集到达,并展示了如何将其应用于比特币交易数据。这是很有趣的,原因很多。例如,对于交易来说,能够预测在短期内是否有更多…...

自动化运维:Ansible脚本之playbook剧本
目录 一、理论 1.playbooks 2.YAML 3.使用ansible批量安装apache服务 4.定义、引用变量 5.指定远程主机sudo切换用户 6.when条件判断 7.迭代 8.Templates 模块 9.tags 模块 10.Roles 模块 二、实验 1.使用ansible批量安装apache服务 2.定义、引用变量…...

基于角色访问控制-RBAC(Role-Based Access Control)
1.RBAC简介 RBAC(Role-Based Access Control)是一种基于角色的访问控制模型,它是一种安全策略,用于限制系统中用户对资源的访问权限。RBAC模型的核心概念是用户角色和资源访问权限。 在角色访问控制中,首先需要定义系…...

springboot项目实现断点续传
java代码 package com.ruoyi.web.upload.controller; import com.ruoyi.web.upload.dto.FileChunkDTO; import com.ruoyi.web.upload.dto.FileChunkResultDTO; import com.ruoyi.web.upload.result.Result; import com.ruoyi.web.upload.service.IUploadService; import org.s…...

解析经典面试题:for 循环中的 let var
更多文章可以看看我的博客:https://icheng.github.io/ 题目 for循环中,使用 var 或 let 声明 i 变量,会得到不同的结果 var arr []; for (var i 0; i < 2; i) {arr[i] function () {console.log(i);} } arr[0](); arr[1]();输出&…...

CSS按钮-跑马灯边框
思路很简单,实现方法有很多很多。但是大体思路与实现方法都类似:渐变色 动画,主要区别在动画的具体实现 0、HTML 结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…...

【PCIE系统学习】Gen1/2Gen3/4 symobl与OrderSet概念对比
这个专栏要干的事:学习PCIE理论知识,学会PCIE IP/VIP的使用。可以达到上手做项目,而不是空有理论 适合谁看:正在学习PCIE 设计验证,但学的过于零散。想有对比的系统的学习。 低价收费的目的:抵制胡乱传播转载现象。 版本控制:便于增加内容以及勘误 版本说明v20230829 …...

C++ Qt 中QMimeDatabase类详细介绍以及应用场景
C Qt 中QMimeDatabase类详细介绍以及应用场景 文章目录 C Qt 中QMimeDatabase类详细介绍以及应用场景一、QMimeDatabase类是什么?二、QMimeDatabase类中的关键功能和特点三、QMimeDatabase的用法四、QMimeDatabase的应用场景 一、QMimeDatabase类是什么?…...

深度学习7:生成对抗网络 – Generative Adversarial Networks | GAN
生成对抗网络 – GAN 是最近2年很热门的一种无监督算法,他能生成出非常逼真的照片,图像甚至视频。我们手机里的照片处理软件中就会使用到它。 目录 生成对抗网络 GAN 的基本原理 大白话版本 非大白话版本 第一阶段:固定「判别器D」&#x…...

R语言空气污染数据的地理空间可视化和分析:颗粒物2.5(PM2.5)和空气质量指数(AQI)...
原文链接:http://tecdat.cn/?p23800 由于空气污染对公众健康的不利影响,人们一直非常关注。世界各国的环境部门都通过各种方法(例如地面观测网络)来监测和评估空气污染问题(点击文末“阅读原文”获取完整代码数据&…...

实现excel导出最简单方式
今天来记录一下导出excel的实现方式,导出的格式是xlsx的文件。 这里用到的是hutool的工具包,依赖如下: <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.5&…...

【每日一题Day310】LC1654到家的最少跳跃次数 | BFS
到家的最少跳跃次数【LC1654】 有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发,到达它的家。 跳蚤跳跃的规则如下: 它可以 往前 跳恰好 a 个位置(即往右跳)。它可以 往后 跳恰好 b 个位置(即往左跳&…...

[Android AIDL] --- AIDL原理简析
上一篇文章已经讲述了如何在Android studio中搭建基于aidl的cs模型框架,只是用起来了,这次对aidl及cs端如何调用的原理进行简单分析 1 创建AIDL文件 AIDL 文件可以分为两类。 一类是用来定义接口方法,声明要暴露哪些接口给客户端调用&#…...

企业的固定资产管理怎么操作
一家拥有多台大型设备的工厂,这些设备需要定期进行保养和维护,以确保其正常运转。而企业内部员工由于专业知识和技能的不同,需要分工协作才能更好地完成各项工作任务。因此,在设备资产管理方面,如何实现高效、便捷、透…...

Rust 进阶学习
Rust 进阶学习 文章目录 Rust 进阶学习所有权作用域移动和克隆涉及函数的所有权机制涉及参数的所有权涉及返回值的所有权 引用和租借可变引用 枚举类枚举成员的属性枚举匹配 结构体结构体方法结构体关联函数 错误处理不可恢复错误可恢复错误 Rust代码组织管理Module默认的Modul…...

保护网站安全:学习蓝莲花的安装和使用,复现跨站脚本攻击漏洞及XSS接收平台
这篇文章旨在用于网络安全学习,请勿进行任何非法行为,否则后果自负。 环境准备 一、XSS基础 1、反射型XSS 攻击介绍 原理 攻击者通过向目标网站提交包含恶意脚本的请求,然后将该恶意脚本注入到响应页面中,使其他用户在查看…...

Redis——如何解决redis穿透、雪崩、击穿问题
目录 一、查询商品信息的常规代码示例二、缓存击穿2.1、缓存击穿的理解2.2、缓存击穿的解决方案2.3、解决缓存击穿的代码示例 三、缓存雪崩3.1、缓存雪崩的理解3.2、缓存雪崩的解决方案3.2.1、缓存集中过期的情况3.2.2、缓存服务器宕机的情况3.2.3、缓存服务器断电的情况 3.3、…...

MySQL一行记录是如何存储的?
目录 MySQL的数据存放在哪个文件? 表空间文件的结构是怎么样的? 1、行(row) 2、页(page) 3、区(extent) 4、段(segment) InnoDB 行格式有哪些…...

[element-ui] el-tree全部展开与收回
shrinkTreeNode () {// 改变一个全局变量this.treeStatus !this.treeStatus;// 改变每个节点的状态this.changeTreeNodeStatus(this.$refs.attrList.store.root); },// 改变节点的状态 changeTreeNodeStatus (node) {node.expanded this.treeStatus;for (let i 0; i < no…...

git 统计(命令)
查询某人某个时刻提交了多少代码 added 添加代码 removed 删除代码 total 总代码 git log --author刘俊秦 --since2023-08-01 00:00:00 --until2023-08-23 23:00:00 --prettytformat: --numstat | awk { add $1; subs $2; loc $1 - $2 } END { printf "added lines: %s…...

斐波那契1(矩阵快速幂加速递推,斐波那契前n项平方和)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 Keven 特别喜欢斐波那契数列,已知 fib11fib_11fib11,fib21fib_21fib21,对于 n>3n>3n>3,fibnfibn−2fibn−1fib_{n}fib_{n-2}fib_{n…...

minikube mac 启动
系统信息如下 最开始使用的minikube是1.22.0版本,按照如下命令启动: minikube start --memory7851 --cpus4 --image-mirror-countrycn遇到了下面一些问题: 1、拉取coredns:v1.8.0镜像失败 Error response from daemon: manifest for regis…...

从零开始学习 Java:简单易懂的入门指南之查找算法及排序算法(二十)
查找算法及排序算法 常见的七种查找算法:1. 基本查找2. 二分查找3. 插值查找4. 斐波那契查找5. 分块查找6. 哈希查找7. 树表查找 四种排序算法:1. 冒泡排序1.1 算法步骤1.2 动图演示1.3 代码示例 2. 选择排序2.1 算法步骤2.2 动图演示 3. 插入排序3.1 算…...