回炉重造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

相关文章

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为