JVM并发编程AQSsync锁ReentrantLock线程池ThreadLocal

并发编程2

    • synchronized锁实现
    • **AQS**
    • **ReentrantLock实现**
    • **JUC 常用类**
    • 池的概念
  • ThreadLocal
    • ThreadLocal原理
    • 内存泄露
    • 强引用:
    • 软引用
    • 弱引用
    • 虚引用
    • ThreadLocal内存泄露

synchronized锁实现

synchronized是一个关键字,实现同步,还需要我们提供一个同步锁对象,记录锁状态,记录线程信息

控制同步,是依靠底层的指令实现的.

如果是同步方法,在指令中会为方法添加ACC_SYNCHRONIZED标志

如果是同步代码块,在进入到同步代码块时,会执行monitorenter, 离开同步代码块时或者出异常时,执行monitorexit

AQS

AQS(AbstractQueuedSynchronizer 抽象同步队列) 是一个实现线程同步的框架

并发包中很多类的底层都用到了AQS

class AbstractQueuedSynchronizer {private transient volatile Node head;private transient volatile Node tail;private volatile int state; //表示有没有线程访问共享数据  默认是0 表示没有线程访问//修改状态的方法protected final boolean compareAndSetState(int expect, int update) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update);}static final class Node {volatile Node prev;volatile Node next;volatile Thread thread;}}

ReentrantLock实现

ReentrantLock完全同过java代码控制

 class ReentrantLock{abstract static class Sync extends AbstractQueuedSynchronizer {abstract void lock();}//非公平锁static final class NonfairSync extends Sync {void lock(){}}//公平锁static final class FairSync extends Sync {void lock(){}}}

在这里插入图片描述

JUC 常用类

在集合类中,像Vector,Hashtable这些类加锁时都是直接把锁加载方法上了,性能就低, 在并发访问量小的情况下,还可以使用, 大并发访问量下,性能就太低了.

ConcurrentHashMap

 HashMap适合单线程场景下的,不允许多个线程同时访问操作,如果有多线程访问会报异常Hashtable 是线程安全的 直接给方法加锁,效率低ConcurrentHashMap 是线程安全的,没有直接给方法加锁, 用哈希表中每一个位置上的第一个元素(第一个是存在元素)作为锁对象哈希表长度是16,那么就有16把锁对象,锁住自己的位置即可,这样如果多个线程如果操作不同的位置,那么相互不影响,只有多个线程操作同一个位置时,才会等待如果位置上没有任何元素,那么采用cas机制插入数据到对应的位置Hashtable ,ConcurrentHashMap  键值都不能为null为什么这样设计,键值都不能为null?map.put("b","b")为了消除歧义  System.out.println(map1.get("a"));//null  值是null  还是键不存在返回null

CopyOnWriteArrayList

ArrayList 是单线程场景下使用的,在多线程场景下会报异常
Vector 是线程安全的,在方法上加了锁,效率低
CopyOnWriteArrayList  写方法操作加了锁(ReentrantLock实现的),
在写入数据时,先把原数组做了备份,把要添加的数据写入到备份数组中,当写入完成后,再把修改的数组赋值到原数组中去
给写加了锁,读没有加锁,读的效率变高了, 这种适合写操作少,读操作多的场景

CopyOnWriteArraySet

CopyOnWriteArraySet 的实现基于 CopyOnWriteArrayList,不能存储重复数据。

辅助类 CountDownLatch

池的概念

字符串常量池

String s1 = “abc”; String s2=“abc”; s1==s2//true

Integer自动装箱 缓存了-128 --+127之间的对象

Integer a = 100; Integer b = 100; a==b //true IntegerCache.cache[i + (-IntegerCache.low)];

数据库连接池

阿里巴巴Druid数据库连接池

帮我们缓存一定数量的链接对象,放在池子里,用完还回到池子中,

减少了对象的频繁创建和销毁的时间开销

线程池

在这里插入图片描述

为减少频繁的创建和销毁线程,

jdk5开始引入了线程池,

建议使用ThreadPoolExecutor类来创建线程池, 这样提高效率.

Java.uitl.concurrent.ThreadPoolExecutor

 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)

7个参数

corePoolSize: 核心线程池中的数量(初始化的数量) 5

maximumPoolSize:线程池中最大的数量 10 5

keepAliveTime: 空闲线程存活时间 当核心线程池中的线程足以应付任务时, 非核心线程池中的线程在指定空闲时间到期后,会销毁.

unit: 时间单位

workQueue: 5 等待队列, 当核心线程池中的线程都在使用时,如果有任务继续到来,会先将等待的任务放到队列中,如果队列也满了,才会创建新的线程(非核心线程池中的线程)

threadFactory:线程工厂,用来创建线程池中的线程

handler:拒绝处理任务时的策略 4种拒绝策略

线程池工作流程

当有大量的任务到来时,先判断核心线程池中的线程是否都忙着,

​ 有空闲的,直接让核心线程中的线程执行任务

​ 没有空闲的, 判断等待队列是否已满,

​ 如果没满,把任务添加到队列等待

​ 如果已满,判断非核心线程池中的线程是否都忙着

​ 如果有空闲的,没满,交由非核心线程池中的线程执行

​ 如果非核心线程池野已经满了,那么就使用对应的拒绝策略处理.

4种拒绝策略:

AbortPolicy: 抛异常

CallerRunsPolicy: 由提交任务的线程执行 例如在main线程提交,则由main线程执行拒绝的任务 DiscardOldestPolicy: 丢弃等待时间最长的任务

DiscardPolicy: 丢弃最后不能执行的任务

提交任务的方法

void   execute(任务);  提交任务没有返回值Future<?> submit = executor.submit(myTask);//提交任务可以接收返回值
submit.get();  

关闭线程池

shutdown();  执行shutdown()后,不再接收新的任务,会把线程池中还有等待队列中已有的任务执行完,再停止
shutdownNow(); 立即停止,队列中等待的任务就不再执行了.
  如果有空闲的,没满,交由非核心线程池中的线程执行

​ 如果非核心线程池野已经满了,那么就使用对应的拒绝策略处理.

4种拒绝策略:

AbortPolicy: 抛异常

CallerRunsPolicy: 由提交任务的线程执行 例如在main线程提交,则由main线程执行拒绝的任务 DiscardOldestPolicy: 丢弃等待时间最长的任务

DiscardPolicy: 丢弃最后不能执行的任务

提交任务的方法

void   execute(任务);  提交任务没有返回值Future<?> submit = executor.submit(myTask);//提交任务可以接收返回值
submit.get();  

关闭线程池

shutdown();  执行shutdown()后,不再接收新的任务,会把线程池中还有等待队列中已有的任务执行完,再停止
shutdownNow(); 立即停止,队列中等待的任务就不再执行了.

ThreadLocal

ThreadLocal中填充的变量属于当前线程,改变量对其他线程而言是隔离的
ThreadLocak为变量在每个线程创建了一个副本,每个线程可以访问自己内部的副本变量

static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
@Overrideprotected Integer initialValue() {return 1;}
};

ThreadLocal原理

首 先 ThreadLocal 是 一 个 泛 型 类 , 保 证 可 以 接 受 任 何 类 型 的 对 象 ,ThreadLocal 内 部 维 护 了 一 个 Map , ThreadLocal 实 现 了 一 个 叫做 ThreadLocalMap 的静态内部类。
而我们使用的 get()、set() 方法其实都是由这个 ThreadLocalMap 类对应的 get()、set() 方法实现的。首 先 ThreadLocal 是 一 个 泛 型 类 , 保 证 可 以 接 受 任 何 类 型 的 对 象 。

在这里插入图片描述
在这里插入图片描述
最终变量是放在当前线程的ThreadLocalMap中,并不是存在ThreadLocal上,ThreadLocal主要作为key,用于存读操作

内存泄露

当对象已经不再被引用,但是垃圾回收机制无法回收该对象,就会产生内存泄露问题(例如数据库链接对象,流对象,socker)

强引用:

当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。

强引用是我们最常见的普遍对象引用,只要还有强引用指向一个对象,就能表明对象还活着,垃圾收集器不会碰这种对象。在JAVA最常见的就是强引用,把一个对象赋给一个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收,因此强引用时造成Java内存泄漏的主要原因之一。

对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用复制为null,一版认为就是可以背垃圾收集了。

public class StrongReferenceDemo {public static void main(String []args) {Object obj1 = new Object(); //这样定义默认是强引用Object obj2 = obj1;obj1 = null;System.gc();System.out.println(obj1);System.out.println(obj2);}
}

对象如果有强引用关系,必定不会被回收

软引用

软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference类来实现,可以让对象豁免一些垃圾收集,对于只有软引用的对象来说,

当系统内存充足时它不会被回收,当系统内存不足时它会被回收。

软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收!

public class SoftReferenceDemo {public static void main(String []args) {Object o1 = new Object();SoftReference<Object> softReference = new SoftReference<Object>(o1);System.out.println(o1);System.out.println(softReference.get());o1 = null;System.gc();try {byte[] bytes = new byte[30*1024*1024];} finally {System.out.println(o1);System.out.println(softReference.get());}}
}

弱引用

弱引用需要用java.lang.ref.WeakReference类来实现,它比软引用的生存区更短。

对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,都会回收该对象占用的内存。

public class WeakReferenceDemo {public static void main(String[] args) {Object o1 = new Object();WeakReference<Object> weakReference = new WeakReference<Object>(o1);System.out.println(o1);System.out.println(weakReference.get());o1 = null;System.gc();System.out.println("----------------------------");System.out.println(o1);System.out.println(weakReference.get());}
}

虚引用

虚引用需要java.lang.ref.PhantomReference类来实现。

顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时间都可能被垃圾回收

器回收,它不能单点使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。

虚引用的主要作用是跟踪对象被垃圾回收的状态,仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。PhantomReference的get方法总是返回null,因此无法访问对应的引用对象,其意义在于说明一个对象已经进入了finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。

换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。Java技术允许使用fianlize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作

public class PhantomReferenceDemo {public static void main(String []args) throws Exception {Object o1 = new Object();ReferenceQueue<Override> referenceQueue = new ReferenceQueue<>();PhantomReference<Object> phantomReference = new PhantomReference(o1,referenceQueue);System.out.println(o1);System.out.println(phantomReference.get());System.out.println(referenceQueue.poll());System.out.println("-----------------");o1 = null;System.gc();Thread.sleep(500);System.out.println(o1);System.out.println(phantomReference.get());System.out.println(referenceQueue.poll());}
}

ThreadLocal内存泄露

在这里插入图片描述
TreadLocalMap 使用 ThreadLocal 的弱引用作为 key,如果一个 ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被 GC 回收,这样就会导致ThreadLocalMap 中 key 为 null, 而 value 还存在着强引用,只有 thead 线程退出以后,value 的强引用链条才会断掉。
但如果当前线程再迟迟不结束的话,这些 key 为 null 的 Entry 的 value 就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value

永远无法回收,造成内存泄漏。
ThreadLocal 正确的使用方法
每次使用完 ThreadLocal 都调用它的 remove()方法清除数据。

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

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

相关文章

C++从入门到入土(八)——多态的原理

目录 前言 多态的原理 动态绑定与静态绑定 虚函数表 小结 前言 在前面的文章中&#xff0c;我们介绍了C三大特性之一的多态&#xff0c;我们主要介绍了多态的构成条件&#xff0c;但是对于多态的原理我们探讨的是不够深入的&#xff0c;下面这这一篇文章&#xff0c;我们将…

自带多个接口,完全免费使用!

做自媒体的小伙伴们&#xff0c;是不是经常为语音转文字的事儿头疼&#xff1f; 今天给大家推荐一款超实用的语音转文字软件——AsrTools&#xff0c;它绝对是你的得力助手&#xff01; AsrTools 免费的语音转文字软件 这款软件特别贴心&#xff0c;完全免费&#xff0c;而且操…

国内首款载重1吨级无人运输机TP1000首飞成功 2026年投入应急救援

大湾区经济网珠海快讯&#xff0c;据央视新闻报道&#xff0c;3月15日上午&#xff0c;国内首款载重1吨级大型无人运输机TP1000在山东成功首飞。该机由中国民航适航标准完全自主研发&#xff0c;起飞重量3.3吨&#xff0c;满载航程达1000公里&#xff0c;具备智能空投功能&…

设计模式Python版 访问者模式

文章目录 前言一、访问者模式二、访问者模式示例 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&#xff1a;关注类和对象之间的组…

(性能测试)性能测试工具 2.jmeter的环境搭建 3jmeter元件和4使用实例 5jmeter元件和参数化

目录 性能测试工具 性能测试工具 jemeter环境搭建 jmeter的常用目录介绍 jmeter修改语言和主题--jmeter界面的汉化 jmeter元件 jmeter元件和组件的介绍 jmeter的作用域原则 jmeter的执行顺序 案例&#xff1a;执行顺序 jmeter使用案例 jmeter线程组的介绍 jmeter…

书摘 ASP.NET Core技术内幕与项目实战:基于DDD与前后端分离

IT行业的发展瞬息万变,新技术层出不穷,很多技术人员出于个人兴趣、个人职业发展等考虑而选择一些流行的新技术,他们会把各种复杂的架构模式、高精尖的技术都加入架构中,这增加了项目的复杂度、延长了交付周期、增加了项目的研发成本。有些技术并不符合公司的情况,最后项目…

Spring Cloud 负载均衡(Ribbon)- 流量管理与服务调用优化

一、Spring Cloud Ribbon 概述 1、什么是 Spring Cloud Ribbon&#xff1f; Spring Cloud Ribbon 是一个基于客户端的负载均衡器&#xff0c;其核心目标是为微服务架构中的服务调用提供智能流量分发能力。与传统的服务端负载均衡&#xff08;如 Nginx&#xff09;不同&#x…

内网环境安装dlv,本地远程调试go

背景&#xff1a;内网环境(服务器)下安装dlv,本地通过dlv调试编译后的go代码。 可以配合观看: 【dlv远程调试-哔哩哔哩】 https://b23.tv/NqPZ5q9 内网安装dlv步骤 1、dlv安装: &#xff08;我额服务器和内网的go都是1.21以上&#xff09; # 先在有网络的环境下&#xff08…

C# MVC项目部署II后错误,403禁止访问:访问被拒绝问题处理

C# MVC项目部署II后错误&#xff0c;403禁止访问&#xff1a;访问被拒绝问题处理 问题如下&#xff1a; 解决办法&#xff1a; 1. 应用程序池要选v4.xx&#xff0c;托管模式选“集成” 2. 把asp.net 4.xx安装在iis上&#xff0c;方法&#xff1a; cd \Windows\Microsoft .NE…

基于Flask的东方财富网股票数据可视化分析系统

【大数据】基于Flask的东方财富网股票数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统能够高效地从东方财富网抓取股票数据&#xff0c;并通过Python的强大数据处理能…

整形在内存中的存储(例题逐个解析)

目录 一.相关知识点 1.截断&#xff1a; 2.整形提升&#xff1a; 3.如何 截断&#xff0c;整型提升&#xff1f; &#xff08;1&#xff09;负数 &#xff08;2&#xff09;正数 &#xff08;3&#xff09;无符号整型&#xff0c;高位补0 注意&#xff1a;提升后得到的…

HarmonyOS第26天:应用发布与推广全攻略:从0到1走向市场

一、引言:开启 HarmonyOS 应用之旅 在数字化时代的浪潮中,HarmonyOS 以其独特的分布式理念和强大的跨设备协同能力,为应用开发领域开辟了一片崭新的天地。随着 HarmonyOS 市场份额的稳步增长,其生态设备数量已突破 9 亿大关,吸引了超过 254 万开发者投身其中 ,成为了开发…

【操作系统安全】任务4:Windows 系统网络安全实践里常用 DOS 命令

目录 一、引言 二、网络信息收集类命令 2.1 ipconfig 命令 2.1.1 功能概述 2.1.2 实例与代码 2.2 ping 命令 2.2.1 功能概述 2.2.2 实例与代码 2.3 tracert 命令 2.3.1 功能概述 2.3.2 实例与代码 三、网络连接与端口管理类命令 3.1 netstat 命令 3.1.1 功能概述…

《我的Python觉醒之路》之转型Python(十五)——控制流

[今天是2025年3月17日&#xff0c;继续复习第一章节、第二章节的内容 ] 《我的Python觉醒之路》之转型Python&#xff08;十四&#xff09;——控制流

通过 SVG 使用 AI 生成理想图片:技术实现与实践指南

文章目录 1. SVG 与 AI 的结合&#xff1a;技术价值2. 技术原理&#xff1a;AI 如何生成 SVG&#xff1f;3. 实现步骤&#xff1a;从需求到图形3.1 定义需求3.2 使用 AI 生成 SVG3.3 验证与调整 4. 代码解析&#xff1a;实现科技感的关键4.1 渐变背景4.2 网格线条4.3 发光六边形…

OpenCV计算摄影学(22)将输入的彩色图像转换为两种风格的铅笔素描效果函数pencilSketch()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 铅笔风格非写实线描图。 该函数通过图像处理技术将输入的彩色图像转换为两种风格的铅笔素描效果&#xff1a; dst1&#xff1a;炭笔效果的灰度图…

JavaScript运算符与流程控制详解

一、运算符 • 赋值运算符 • 一元运算符 • 比较运算符 • 逻辑运算符 • 运算符优先级 1.算术运算符 数字是用来计算的&#xff0c;比如&#xff1a;乘法 * 、除法 / 、加法 、减法 - 等等&#xff0c;所以经常和算术运算符一起。 算术运算符&#xff1a;也叫数学运算符&…

设计模式(行为型)-观察者模式

目录 定义 类图 角色 Subject&#xff1a;抽象主题&#xff08;抽象被观察者&#xff09;​ ConcreteSubject&#xff1a;具体主题&#xff08;具体被观察者&#xff09;​ Observer&#xff1a;抽象观察者​ ConcrereObserver&#xff1a;具体观察者​ 优缺点 优点​…

调用华为云API实现口罩识别

1.作者介绍 范小雨&#xff0c;女&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;1019044907qq.com 高金年&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生&#…

C++中的单例模式及具体应用示例

AI 摘要 本文深入探讨了C中的单例模式及其在机器人自主导航中的应用&#xff0c;特别是如何通过单例模式来管理地图数据。文章详细介绍了单例模式的基本结构、优缺点以及在多线程环境中的应用&#xff0c;强调了其在保证数据一致性和资源管理中的重要性。 接着&#xff0c;文章…