并发编程(第二天)

interrupt 方法详解

  • 打断 sleep,wait,join 的线程 这几个方法都会让线程进入阻塞状态 打断 sleep 的线程, 会清空打断状态
  • 打断正常运行的线程 打断正常运行的线程, 不会清空打断状态
  • 打断 park 线程 打断 park 线程, 不会清空打断状态

如果打断标记已经是 true, 则 park 会失效

两阶段终止模式

class TPTInterrupt {private Thread thread;public void start(){thread = new Thread(() -> {while(true) {Thread current = Thread.currentThread();if(current.isInterrupted()) {log.debug("料理后事");break;}try {Thread.sleep(1000);log.debug("将结果保存");} catch (InterruptedException e) {current.interrupt();}// 执行监控操作               }
},"监控线程");
thread.start();
}public void stop() {thread.interrupt();}}

 调用

TPTInterrupt t = new TPTInterrupt();t.start();Thread.sleep(3500);log.debug("stop");t.stop();
  • 11:49:42.915 c.TwoPhaseTermination [监控线程] - 将结果保存
  • 11:49:43.919 c.TwoPhaseTermination[监控线程] - 将结果保存
  • 11:49:44.919 c.TwoPhaseTermination[监控线程] - 将结果保存
  • 11:49:45.413 c.TestTwoPhaseTermination [main] - stop
  • 11:49:45.413 c.TwoPhaseTermination[监控线程] - 料理后事 

主线程与守护线程

默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守 护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

log.debug("开始运行...");Thread t1 = new Thread(() -> {log.debug("开始运行...");sleep(2);log.debug("运行结束...");}, "daemon");// 设置该线程为守护线程
t1.setDaemon(true);t1.start();sleep(1);log.debug("运行结束...");
  •  垃圾回收器线程就是一种守护线程
  • Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等 待它们处理完当前请求

五种状态(线程)

从 操作系统 层面来描述

【初始状态】仅是在语言层面创建了线程对象,还未与操作系统线程关联

【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执行

【运行状态】指获取了 CPU 时间片运行中的状态

  • 当 CPU 时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换

【阻塞状态】

  • 如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU,会导致线程上下文切换,进入 【阻塞状态】
  • 等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
  • 与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑 调度它们

【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态

六种状态

是从 Java API 层面来描述

根据 Thread.State 枚举,分为六种状态

  • NEW 线程刚被创建,但是还没有调用 start() 方法
  • RUNNABLE 当调用了 start() 方法之后,注意,Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的 【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为 是可运行)
  • BLOCKED , WAITING , 详述 TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分,后面会在状态转换一节
  • TERMINATED 当线程代码运行结束

共享模型之管程

临界区 Critical Section

一个程序运行多个线程本身是没有问题的

问题出在多个线程访问共享资源

  • 多个线程读共享资源其实也没有问题
  • 在多个线程对共享资源读写操作时发生指令交错,就会出现问题

一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

竞态条件 Race Condition

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

synchronized

俗称的【对象锁】,它采用互斥的方式让同一 时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住。这样就能保证拥有锁 的线程可以安全的执行临界区内的代码,不用担心线程上下文切换

语法 

synchronized(对象) // 线程1, 线程2(blocked)
{临界区
}
static int counter = 0;static final Object room = new Object();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {synchronized (room) {counter++;}}}, 
"t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {synchronized (room) {counter--;}}}, 
"t2");}t1.start();t2.start();t1.join();t2.join();log.debug("{}",counter);

加上同一把对象所之后结果就只会是0,不会因为多线程问题导致结果不唯一。 

方法上的 synchronized

class Test{public synchronized void test() {}
}
等价于
class Test{public void test() {synchronized(this) {}}}
 class Test{public synchronized static void test() {}}
等价于
class Test{public static void test() {synchronized(Test.class) {}}

加在普通方法上表示锁的对象是自己

加在静态方法上表示锁的对象是类(字节码) 

所谓的“线程八锁”

情况1: 12 或 21

 @Slf4j(topic = "c.Number")class Number{public synchronized void a() {log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}

 情况2: 1s后12,或 2 1s后 1 

 @Slf4j(topic = "c.Number")class Number{public synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}

情况3: 3 1s 12 或 23 1s 1 或 32 1s 1

@Slf4j(topic = "c.Number")
class Number{public synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}public void c() {log.debug("3");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();new Thread(()->{ n1.c(); }).start();}

过多也就不展示了,本质上其实就是考察 synchronized 锁住的是哪个对象 

 

 

 

 

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

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

相关文章

【Python】线性规划模型(笔记)

线性规划的作用 求一个线性目标函数在线性可行域内的最值问题 线性规划的典型应用 配送运输问题&#xff1a;选大车还是小车生产规划问题&#xff1a;每种原料各买多少几何切割问题&#xff1a;切割长宽各多少买卖利润问题&#xff1a;最多能挣多少钱… 线性规划的本质 问…

C语言FTP文件传输(完成基本文件传输的功能)

文章目录 前言一、实现思路二、实现FTP服务器三、实现FTP客户端四、实现体验总结 前言 本篇文章带大家来完成一下C语言FTP文件传输助手最基础的功能&#xff0c;也就是客户端和服务器之间进行最基础的文件传输的功能。 一、实现思路 实现一个基本的 FTP 客户端和服务器&…

【生成式人工智能-十一一个不修改模型就能加速语言模型生成的方法】

一个加速语言模型生成的方法 现在语言模型的一个弊端speculative decoding预言家预测的问题 speculative decoding 模块的实现方法NAT Non-autoregressive模型压缩使用搜索引擎 一些更复杂些的speculative decoding 实现方式 speculative decoding 是一个适用于目前生成模型的加…

WSL 忘记ubuntu的密码

文章目录 1. 以管理员身份打开 PowerShel2.输入命令 wsl.exe -d Ubuntu-20.04 --user root3.输入命令 passwd username 修改用户密码&#xff0c;username即待重置的用户的名称 1. 以管理员身份打开 PowerShel 2.输入命令 wsl.exe -d Ubuntu-20.04 --user root 注意版本号是自…

Springboot整合Flowable入门-学习笔记

目录 1、定义流程&#xff08;画图&#xff09; 2、Springboot部署流程 3、Springboot删除所有流程 4、Springboot根据 流程部署ID 查询 流程定义ID 5、Springboot启动(发起)流程 6、Springboot查询任务 6.1全部任务 6.2我的任务&#xff08;代办任务&#xff09; 7、…

JVM知识总结(性能调优)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 性能调优 何时进行JVM调优&#xff1f; 遇到以下情况&#xff0c…

傻瓜式一步到位Mysql 8.0 密码修改

5.7之前修改密码语句 update user set authentication_string password(“root”) where user “root”; mysql 5.7.9以后废弃了password字段和password()函数&#xff1b;并在user表加了authentication_string:字段表示用户密码 #进入到mysql 安装目录下 #停止 mysql 服务 …

怎么调试python脚本

打开pycharm community 2019.1软件&#xff0c;创建一个项目。 创建一个py后缀的文件作为示范&#xff0c;文件名自己定义。 编写代码&#xff0c;然后右键点击进行运行&#xff0c;查看一下是否有问题。 点击右上角的虫子图标&#xff0c;然后下面会有控制面板出来&#xff0c…

基于C11的简单log,支持C++的‘<<’风格和C的‘可变参数’风格

基于C11的简单log&#xff0c;支持C的‘<<’风格和C的‘可变参数’风格 日志仅由richlog.h单个文件实现功能&#xff0c;软件集成简单。 支持C的std::cout的<<风格的日志打印&#xff0c;也支持C的printf风格的日志打印 日志多线程安全&#xff0c;采用C11 mute…

SpringBoot整合日志功能(slf4j+logback)详解

目录 一、日志门面与日志实现 1.1 什么是日志门面和日志实现&#xff1f; 1.2 为什么需要日志门面&#xff1f; 二、简介 三、日志格式 四、记录日志 4.1 使用日志工厂 4.2 使用Lombok的Slf4j注解 五、日志级别 5.1 日志级别介绍 5.2 配置日志级别 5.3 指定某个包下…

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 文章目录 前言分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 一、PSO-KELM-Adaboost模型1. 核化极限学习机 (KELM)2. 粒子…

数据库原理面试-核心概念-问题理解

目录 1.数据库、数据库系统与数据库管理系统 2.理解数据独立性 3.数据模型 4.模式、外模式和内模式 5.关系和关系数据库 6.主键与外键 7.SQL语言 8.索引与视图 9.数据库安全 10.数据库完整性 11.数据依赖和函数依赖 12.范式&#xff1f;三范式&#xff1f;为什么要遵…

用栈访问最后若干元素——682、71、388

682. 棒球比赛&#xff08;简单&#xff09; 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[…

【redis的大key问题】

在使用 Redis 的过程中&#xff0c;如果未能及时发现并处理 Big keys&#xff08;下文称为“大Key”&#xff09;&#xff0c;可能会导致服务性能下降、用户体验变差&#xff0c;甚至引发大面积故障。 本文将介绍大Key产生的原因、其可能引发的问题及如何快速找出大Key并将其优…

基于llama.cpp实现Llama3模型的guff格式转换、4bit量化以及GPU推理加速(海光DCU)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 序言 本文使用llama.cpp框架&#xff0c;对 Llama3-8B-Instruct 模型进行gguf格式转换&#xff0c;8bit量化&#xff0c;并在CPU和GPU上对8bit模型进行推理。 测试…

基于SpringBoot的企业资产管理系统

TOC springboot117基于SpringBoot的企业资产管理系统 系统概述 1.1 研究背景 智慧养老是面向居家老人、社区及养老机构的传感网系统与信息平台&#xff0c;并在此基础上提供实时、快捷、高效、低成本的&#xff0c;物联化、互联化、智能化的养老服务。 随着科技进步&#…

mysql中log

目录 MySQL 日志系统概述 日志类型 日志的作用和重要性 Mermaid图示 1. Undo Log 和 Redo Log 的协同工作图 2. Redo Log 确保持久性的流程图 Undo Log&#xff08;回滚日志&#xff09; 事务的原子性&#xff08;Atomicity&#xff09;保障 事务回滚机制 MVCC&#…

【二叉树进阶】--- 二叉搜索树转双向链表 最近公共祖先

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 数据结构 本篇博客我们继续了解一些二叉树的进阶算法。 &#x1f3e0; 二叉搜索 树转化为双向循环链表 &#x1f4cc; 题目内容 将二叉搜索树转化为排序…

失败:Windows--WSL2--Ubuntuon--Docker

编写目的&#xff1a; 在Windows上安装Docker&#xff0c;用Docker安装Gitlab、Jenkins等软件。 文章记录一下Windows上安装Docker的过程。 参考文档&#xff1a; 旧版 WSL 的手动安装步骤 | Microsoft Learn 下面用"参考文档"代替 目录 第一步&#xff1a;启…

SAP与网易大数据系统集成案例

一、项目环境 江西某药业有限公司是一家以医药产业为主营、资本经营为平台的大型民营企业集团。公司成立迄今&#xff0c;企业经营一直呈现稳健、快速发展的态势集团总销售额超40亿元。 为了帮助企业更有效的进行分配和管理&#xff0c;包括人力、物资、时间和预算等资源&a…