JUC并发编程(二)
一、过时方法
一些不推荐使用的方法已经过时,容易破坏同步代码块,使对象的锁得不到释放,进而造成线程死锁

二、守护线程
默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。
正常情况下:主线程运行结束,但t1线程仍未结束,因此进程并不会结束(只要有一个线程还在运行,Java进程并不会结束)

将t1设置为守护线程后:
import lombok.extern.slf4j.Slf4j;@Slf4j(topic = "c.Test15")
public class Test15 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {break;}}log.debug("结束");}, "t1");// 将t1设置为守护线程(默认值为非守护线程:false)t1.setDaemon(true); t1.start();Thread.sleep(1000);log.debug("结束");}
}
运行结果:主线程(非守护)运行结束后,无论守护线程(t1)是否执行完毕均会强制结束

守护线程应用:
● 垃圾回收器线程就是一种守护线程【再堆内存中分配的对象,当没有其它对象引用这些对象时,这些未被引用的对象就会定期被垃圾回收】
● Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等待它们处理完当前请求
三、线程状态(五种)
五种状态,这是从 操作系统 层面来描述的

● 初始状态】仅是在语言层面创建了线程对象,还未与操作系统线程关联(eg:Java中newThread对象,但未调用其start()方法)
● 【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执行,但暂时还未获得CPU的时间片
● 【运行状态】指获取了 CPU 时间片运行中的状态
—— 当 CPU 时间片用完,会从【运行状态】转换至【可运行状态】,其切换会导致线程的上下文切换
● 【阻塞状态】
—— 如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU(调度器不会考虑调度阻塞状态的线程),会导致线程上下文切换,进入【阻塞状态】
—— 等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
—— 与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
● 【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态
四、线程状态(六种)
六种状态,是从Java API层面来描述的
根据Thread.State枚举,分为六种状态

● NEW 线程刚被创建,但是还没有调用 start() 方法
● RUNNABLE 当调用了 start() 方法之后,注意,Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为是可运行)操作系统层面的阻塞状态在Java中还是RUNNABLE
● BLOCKED , WAITING , TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分,后面会在状态转换一节详述
● TERMINATED 当线程代码运行结束
3.1 六种状态演示
import lombok.extern.slf4j.Slf4j;import java.io.IOException;@Slf4j(topic = "c.TestState")
public class TestState {public static void main(String[] args) throws IOException {// ① 并未调用线程1的start()方法===>NEWThread t1 = new Thread("t1") {@Overridepublic void run() {log.debug("running...");}};// ② 不断运行===>RUNNABLE(既有可能分到时间片也有可能为分到时间片,也有可能陷入操作系统的IO阻塞)Thread t2 = new Thread("t2") {@Overridepublic void run() {while(true) { // runnable}}};t2.start();// ③ 打印后执行完毕===>TERMINATEDThread t3 = new Thread("t3") {@Overridepublic void run() {log.debug("running...");}};t3.start();// ④ 线程处于阻塞状态【sleep时间足够长===>TIMED_WAITING(有时限的的等待)】Thread t4 = new Thread("t4") {@Overridepublic void run() {synchronized (TestState.class) {try {Thread.sleep(1000000); // timed_waiting} catch (InterruptedException e) {e.printStackTrace();}}}};t4.start();// ⑤ 等待t2(死循环)一直运行结束===>WAITING(没有时限的等待)Thread t5 = new Thread("t5") {@Overridepublic void run() {try {t2.join(); // waiting} catch (InterruptedException e) {e.printStackTrace();}}};t5.start();// ⑥ t4线程会先对对象加锁,t6线程不能获取对象的锁===>t6陷入BLOCKEDThread t6 = new Thread("t6") {@Overridepublic void run() {synchronized (TestState.class) { // blockedtry {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}};t6.start();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}log.debug("t1 state {}", t1.getState());log.debug("t2 state {}", t2.getState());log.debug("t3 state {}", t3.getState());log.debug("t4 state {}", t4.getState());log.debug("t5 state {}", t5.getState());log.debug("t6 state {}", t6.getState());System.in.read();}
}
运行结果:

四、多线程应用统筹分析
如何使用多线程得到最优方案?

后两种办法均耗费时间较长

上图可以一眼看出,办法甲总共要16分钟(而办法乙、丙需要20分钟)。因此合理分配便可节约大量时间,我们可以使用多线程的思想便可找到最优的方案

方案实现:
import lombok.extern.slf4j.Slf4j;import static cn.itcast.n2.util.Sleeper.sleep;@Slf4j(topic = "c.Test16")
public class Test16 {public static void main(String[] args) {Thread t1 = new Thread(() -> {log.debug("洗水壶");sleep(1);log.debug("烧开水");sleep(5);},"老王");Thread t2 = new Thread(() -> {log.debug("洗茶壶");sleep(1);log.debug("洗茶杯");sleep(2);log.debug("拿茶叶");sleep(1);try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}log.debug("泡茶");},"小王");t1.start();t2.start();}
}
运行结果:

相关文章:
JUC并发编程(二)
一、过时方法 一些不推荐使用的方法已经过时,容易破坏同步代码块,使对象的锁得不到释放,进而造成线程死锁 二、守护线程 默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程…...
Python控制CANoe使能TestCase
前面介绍了多种CANoe配置下的dbc文件添加,常见的配置我们能够常用的就是testcase的使能和环境变量的设置,针对于环境变量的问题,我们下次再进行详聊,今天主要聊一下测试脚本的使能。在做这块之前,我们第一步就需要了解我们的测试脚本的层级是都包含有哪些? 一、测试脚本结…...
sql的执行顺序
一.前言 在我们世家开发中,我们少不了和数据库打交道, 我们的持久层是与数据库打交道的, 少不了要用sql语句来请求数据库的数据, 前台(前端页面)请求到-->控制器(接口层)-->service(业务层)-->mapper或dao(持久层) 简图: 在持久层我们的sql是怎么执行的, 它的执行顺…...
java 8 中的实用技巧
1 判断2个对象是否相等Objects.equals(a, b)(1) 比较时, 若a 和 b 都是null, 则返回 true, 如果a 和 b 其中一个是null, 另一个不是null, 则返回false。注意:不会抛出空指针异常。(2) a 和 b 如果都是空值字符串:"", 则 a.equals(b…...
自学大数据的第一天
默认跳过基础部分,直接搞集群的部分,期间用到的linux基础默认大伙都会了(不会的话可以现用现查) Hadoop集群搭建 集群特点: 1,逻辑上分离~集群之间没有依赖,互不影响 2,某些进程往往部署在一台服务器上,但是属于不同的集群 3,MapReduce 是计算框架,代码层面的处理逻辑 集群的…...
redis秒杀
redis优惠券秒杀 为什么订单表订单ID不采用自增长? id规律性太明显,容易被用户猜测到(比如第一天下订单id10,第二天下订单id100,在昨天的1天内只卖出90商品)受单表数据量限制(订单数据量大&am…...
JS学习第3天——Web APIs之DOM(什么是DOM,相关API【创建、增删改查、属性操作、事件操作API】)
目录一、Web APIs介绍1、API2、Web API二、DOM1、DOM树2、获取元素3、事件基础4、操作元素属性5、节点(node)操作三、DOM操作总结(创建、增删改查、属性操作、事件操作API)1、创建2、增3、删4、改5、查6、属性操作7、事件操作四、…...
【MySQL】增删改操作(基础篇)
目录 1、新增操作(Create) 1.1 单行数据 全列插入 1.2 多行数据 全列插入 1.3 单行数据 指定列插入 2、修改操作(Update) 3、删除操作(Delete) 1、新增操作(Create) 如何给一张表新增数据呢? 新增(Create),在我们数据库中,用 ins…...
STM32—DMA
什么是DMA? DMA(Direct Memory Access,直接存储器访问) 提供在外设与内存、存储器和存储器、外设与外设之间的高速数据传输使用。它允许不同速度的硬件装置来沟通,而不需要依赖于CPU,在这个时间中,CPU对于内存的工作来…...
C语言刷题(3)——“C”
各位CSDN的uu们你们好呀,今天小雅兰的内容还是做几道题噢,好好复习一下之前的知识点,现在,就让我们开始复习吧 牛客网在线编程_编程学习|练习题_数据结构|系统设计题库 倒置字符串_牛客题霸_牛客网 BC40 竞选社长 BC41 你是天才…...
搭建Vue工程
搭建Vue工程 localhost 127.0.0.1 域名 IP 192.168.0.28 联网IP 最后都会渲染到一个页面里面,有多少个页面就有多少个页面模板。 vue里面改webpack配置 vue.config.js 配置参考 | Vue CLI /assets /api* 开发的时候用到的请求后台地址 和 项目真实部署上线的时候 请…...
C语言汉诺塔问题【图文详解】
汉诺塔1. 什么是汉诺塔2. 有关汉诺塔的有趣故事3. 利用动画来演示汉诺塔4. 如何用C语言实现汉诺塔1. 什么是汉诺塔 源于印度古老传说的益智玩具 汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造…...
1、RocketMQ概述
文章目录1 MQ概述1.1 MQ简介1.2 MQ用途1.3 常见MQ产品1.4 MQ常见协议2 RocketMQ概述2.1 RocketMQ简介2.2 RocketMQ发展历程尚硅谷RocketMQ教程-讲师:Reythor雷(老雷) 我们缺乏的不是知识,而是学而不厌的态度 1 MQ概述 1.1 MQ简介…...
【POJ 3352】Road Construction 题解(Tarjan算法求边双连通分量缩点)
描述 现在几乎是夏天,这意味着几乎是夏天的施工时间!今年,负责偏远岛热带岛屿天堂道路的好心人希望修复和升级岛上各个旅游景点之间的各种道路。 道路本身也很有趣。由于岛上的奇怪风俗,道路的安排使得它们不会在交叉路口相遇&…...
Python—单分支结构
(1)if分支语句 Python中if语句的语法结构: if <条件表达式>: 满足条件运行的代码1 满足条件运行的代码2 代码示例: age 12 if age > 18:print(去上网)if 1 1 2 and :print(我满足条件了)if 1 …...
rabbitmq添加用户,虚拟机步,设置rabbitmq配置文件
第一步,登录后台控制页面 http://ip:15672第二步,添加用户和权限 重点:选择Admin和Users 第三步,添加虚拟机 点击侧边的Virtual Hosts 第四步将虚拟机和用户搭配 注意新建好后,在虚拟机列表中,点击虚拟机…...
Codeforces Round#853 div2 A-C
Codeforces Round#853 div2 A-C 等了很久终于迎来了一场cf比赛,白天出去玩了一圈,晚上回来打比赛,这次只出了A,B题。C题思路很巧妙,赛时没做出来,看了大佬学习到了,还是很不错。 A.Serval and Mocha’s A…...
软考之操作系统知识
目录 1.进程管理-进程的概念 2.进程的三态图和五态图 3.进程的同步与互斥 4.PV操作应用 5.死锁问题 6.银行家算法 7.存储管理 8.段式存储组织 9.段页式存储组织 10.页面置换算法 11.磁盘管理 12.作业管理 13.索引文件结构 14.树型目录结构 15.空闲存储空间管理 …...
【线性代数/计算复杂性理论】积和式的指数时间算法:Ryser算法
文章目录一、积和式的定义二、Ryser算法三、代码实现一、积和式的定义 积和式(permanent)是一种和行列式长得很像的矩阵函数。在介绍积和式之前,我们先看看行列式(determinant)的定义。 首先需要引入“排列”&#x…...
代码随想录 NO52 | 动态规划_leetcode 647. 回文子串 516.最长回文子序列
动态规划_leetcode 647. 回文子串 516.最长回文子序列今天是动态规划最后一天的题了,整个过程已经接近尾声了! 647. 回文子串 确定dp数组(dp table)以及下标的含义 本题如果我们定义,dp[i] 为 下标i结尾的字符串有 dp…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
