回炉重造java----JUC(第二天)

2024-06-06 02:04
文章标签 java 第二天 juc 回炉 重造

本文主要是介绍回炉重造java----JUC(第二天),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Monitor---监视器/管程

对象头:

操作系统提供的Monitor对象

Synchronized底层实现原理:

①锁对象在加了synchronized之后,对象头中的Mark Word中就存了一个Monitor的地址指针。

②当一个线程获取到锁之后,Monitor中的Owner属性指向了该获得锁的线程。

③当锁还没释放时,其他的线程来获得锁,就会进入EntryList等待队列中等待。

④当线程2释放锁之后,通知Monitor中的等待队列中的线程,通过一些策略进行选择一个线程拿出来并且获得锁,把Owner指向该获得锁的线程。

⑤当一个线程获取到锁后,发现自身任不满足一些条件,就会调用wait()方法进入Wait_Set中等待(此时线程是进入了Waiting状态),当另一个线程获得锁并且把条件送过来了(即调用notify()唤醒Wait_Set方法中的一个线程或者使用notifyAll()唤醒所有的线程),然后线程就可以再次进入EntryList中去竞争获得锁。

字节码指令:

Synchronized优化/升级

线程状态的转换

1:start():NEW----->Runnable

2:wait():Runnable------> Waiting。notify(),notifyAll(),interrupt():Waiting------>Runnable(注意这里从Waiting转向Runnable是竞争获取到了锁,如果没获取到锁,则会进入Blocked)。

3:join():Runnable------> Waiting。子线程结束或者interrupt():Waiting------>Runnable。

4:park():Runnable------> Waiting。unpark():Waiting------>Runnable。

5:wait(time):Runnable------> Timed_Waiting。超过时间或者被唤醒:Timed_Waiting------>Runnable(注意这里从Timed_Waiting转向Runnable也是竞争获取到了锁,如果没获取到锁,则会进入Blocked)。

6,8:join(time)/parkNanos(time):Runnable------> Timed_Waiting。超过时间或者被唤醒:Timed_Waiting------>Runnable

7:sleep(time):Runnable------> Timed_Waiting。时间到了或者被唤醒:Timed_Waiting------>Runnable。

9:获取锁失败:Runnable------>Blocked。获取锁成功:Runnable------>Blocked。

10:执行代码结束:Runnable------>Terminated。

活锁与死锁

活锁:是一种现象,两个线程一直改变对方的结束条件,导致两个线程都无法结束,一直僵持运行下去。

死锁:死锁是两个线程为了获得锁,并且都需要对象已经占有的锁,导致谁也无法获取的锁,一直僵持死锁状态。

ReentrantLock(可重入锁) 

主要特点:①可中断(其他线程可以通过interrupt()打断正在等待锁的线程)

                  ②可设置超时时间(一个线程尝试获得锁失败后,一般会进行阻塞状态一直等待锁,但是ReentrantLock可设置一个超时时间,当等待时间超过该时间就会自动放弃获得锁)

                  ③可设置为公平锁(先来的线程先获得锁,解决饥饿问题,但是会降低并发度)

                  ④支持多个条件变量(支持多个WaitSet去存放等待的线程,通过Condition中的await()方法去让想线程放进等待室,通过signal()或者signalAll()去唤醒对应休息室的线程)

                  ⑤与Synchronized一样,都支持可重入(可重入就是当一个线程获得了锁之后,如果再次尝试获得该锁也会成功,如果是非重入的话,第二次获得就会把自己锁住)

public class ReentrantLockTest {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {lock.lock();try {System.out.println("我获得了锁,开始操作");m1();}finally {lock.unlock();System.out.println("我释放锁了");}}public static void m1(){lock.lock();try {System.out.println("我重入了锁,要开始我自己的操作");}finally {lock.unlock();System.out.println("我释放锁了");}}
}

同步模式---顺序执行线程

 wait()和notify()方式:

public class SortThreadTest {static final Object lock = new Object(); //锁对象static boolean t2done = false; //t2是否执行的信号public static void main(String[] args) {//创建t1线程new Thread(()->{//获得锁synchronized (lock){while (! t2done){ //判断t2是否已经执行完try {lock.wait(); //如果没有执行,则让出CPU去等待} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("我t1成功执行!!!"); //如果t2已经执行,t1再执行}}).start();//创建t2线程new Thread(()->{//获得锁synchronized (lock){System.out.println("我t2要先执行呀!!!"); //t2要先执行,就直接执行t2done = true; //改变信号lock.notify(); //去WaitSet中唤醒正在等待的t1}}).start();}
}

await()和signal()方式:

public class SortThreadTest01 {//创建ReentrantLock对象private static ReentrantLock reentrantLock = new ReentrantLock();//新建一个WaitSetstatic Condition condition1 = reentrantLock.newCondition();//创建t2完成的信号变量static Boolean t2done = false;public static void main(String[] args) {//创建线程t1new Thread(()->{//获取锁reentrantLock.lock();try {while (! t2done){//t2还没执行,进入WaitSet等待try {condition1.await();} catch (InterruptedException e) {e.printStackTrace();}}//t2执行完毕后,t1执行System.out.println("我t1要在后面执行!!");}finally {//释放锁reentrantLock.unlock();}}).start();//创建线程t2new Thread(()->{//获取锁reentrantLock.lock();try {//t2直接执行System.out.println("我t2要在前面执行!!");//执行完后,设置信号t2done = true;//唤醒t1condition1.signal();}finally {//释放锁reentrantLock.unlock();}}).start();}
}

同步模式---交替执行线程

public class CrossThreadTest {public static void main(String[] args) {test t = new test(1,5);new Thread(()->{t.print("a",1,2);}).start();new Thread(()->{t.print("b",2,3);}).start();new Thread(()->{t.print("c",3,1);}).start();}}class test{public void print(String str,int waitflag,int nextflag){for (int i = 0; i < loopnumber; i++) {synchronized (this){while (flag != waitflag){try {this.wait();}catch (InterruptedException e){e.printStackTrace();}}System.out.print(str);flag = nextflag;this.notifyAll();}}}private int flag;private int loopnumber;public test(int flag, int loopnumber) {this.flag = flag;this.loopnumber = loopnumber;}
}

这篇关于回炉重造java----JUC(第二天)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1034790

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析