
Java并发编程(多线程)
文章平均质量分 93
程序猿进阶
要做就做第一,就算结果不是第一,也会是一个好成绩。 加油!我的未来不是梦。
展开
-
大循环引起CPU负载过高
由于代码中大循环非常小号cpu资源,通过分析这里方法的作用在于遍历判断获取数据,优先使用hashmap代替,用空间换时间,经过修复后重新发布,cpu利用率明显下降,恢复正常。【1】使用循环时需要特别注意大循环,有限使用O(1)的hashmap,大循环对于cpu性能的压榨问题表现的淋淋尽致。【2】镜像机器由于是使用生产流量转发,所以高度贴近生产实际发布,所以每次发布前,先使用镜像机器预发布,可以尽可能的将潜在问题暴露出来,性能实验室中提供了cpu热点,内存分配热点和锁竞争热点的Flamegraph。原创 2024-11-13 05:30:00 · 7755 阅读 · 89 评论 -
Cacheable注解导致线程block
减少getData()方法的调用次数,优化后的一次http请求,平均只需要调用7次getData()方法,并通过压测发现cpu利用率不再异常升高,也不再出现线程block的情况。【1】在业务代码中,尤其是在高qps场景下,需要注意服务调用过程中的临界区,压测作为一种重要的测试手段,通过并发测试可以提高暴露线程安全的问题。【2】在业务多层嵌套的场景中,任何一种方法的不当调用可能就会产生令人难以置信的调用风暴,尤其是在高qps情况下更需要注意,合理减少嵌套层数或者减少调用次数。原创 2024-11-14 05:30:00 · 11541 阅读 · 85 评论 -
线程的六种状态
线程的状态在这个枚举类型中定义:共有6种状态,可以调用线程Thread种的getState()方法获取当前线程状态。原创 2024-09-11 05:15:00 · 9902 阅读 · 54 评论 -
Tomcat Request Cookie 丢失问题
告警,告警后发到工作群中,但是相关开发人员告知自己能够正常访问,没有问题,因为正好周五,自己觉得偶发性肯定和并发相关,所以周末研究了下代码,发现和。请求的类,包含了请求的所有详细信息。该类提供了许多方法来访问和操作请求的各个部分,例如请求头、请求参数、输入流等。(涉及到多线程处理)出现"前端传递`Cookie为空"的告警,导致前端请求丢失,出现请求失败问题。方法),以清除上一次请求的状态,使其可以安全地用于下一个请求。【3】异常处理:在处理请求的过程中,如果发生异常,的时候发现为空,本次请求直接被中止。原创 2024-09-10 05:15:00 · 2630 阅读 · 82 评论 -
ThreadLocal 释放的方式有哪些
创建一个自定义的,在创建线程时添加钩子,以便在任务完成后清理变量。搭建统一线程池平台,对该部分进行了改造。提供多个工厂,就包含自动清理工厂。// 清理ThreadLocal变量 ThreadLocalHolder . clear();} });// 清理ThreadLocal变量 ThreadLocalHolder . clear();} });原创 2024-09-09 05:15:00 · 1698 阅读 · 70 评论 -
JVM 锁的种类
① 如果轻量级锁失败,表示存在竞争,升级为重量级锁(常规锁);② 在没有锁竞争的情况下,减少传统锁使用。原创 2024-08-29 05:30:00 · 2684 阅读 · 85 评论 -
ThreadLoad如何防止内存溢出
因为线程没有关闭,无法回收,但是这些对象不会再被使用了。变量没有其他强依赖,如果当前线程还存在,由于线程的。如果使用线程池,由于线程可能并不是真正的关闭(比如。变量在需要清理的资源管理上下文中使用,可以使用。变量,并且确保在子线程中正确清理,可以考虑使用。对象的引用,是不会释放的,就会造成内存泄漏。的项,这需要实际使用的时候使用完毕及时调用。在上面的代码中,我们可以看出,当前。(调用线程的成员变量),也知道。方法设置变量的时候,当前线程的。:如果需要在子线程中访问父线程的。变量,并在子线程完成后自动清理。原创 2024-08-19 05:30:00 · 2233 阅读 · 47 评论 -
Java 强/软/弱/虚引用
时回收该对象,让其超出对象的生命周期范围或者设置引用指向null,并且会执行对象的`finalize 函数。当jvm扫描到虚引用的对象时,会先将此对象放入关联的队列中,因此我们可以通过判断队列中是否存这个对象,来进行回收前的一些处理。认为强引用的对象是用户正在使用的对象,它无法分辨出到底该回收哪个,强行回收有可能导致系统严重错误。强引用是最普遍的引用,一般把一个对象赋给一个引用变量,这个引用变量就是强引用。虚拟机就会把这个软引用加入到与之关联的引用队列中。虚引用和没有引用是一样的,需要和队列。原创 2024-08-16 05:30:00 · 1139 阅读 · 64 评论 -
CompletableFuture 详解
JDK1.8中的是对Future的扩展和加强。实现了和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力和通过回调的方式处理计算结果,使Java在处理多任务的协同工作时更加顺畅便利。接口定义了任务编排的方法,可以向下执行后续阶段。异步执行的,默认线程池是,但为了业务之间互不影响,且便于定位问题,强烈推荐使用自定义线程池。// 根据commonPool的并行度来选择,而并行度的计算是在ForkJoinPool的静态代码段完成的。原创 2024-05-08 05:00:00 · 1681 阅读 · 72 评论 -
JVM 类加载机制
其中类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。在这五个阶段中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持 Java语言的运行时绑定(也成为动态绑定或晚期绑定)。另外注意这里的几个阶段是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常都是互相交叉地混合进行的,通常在一个阶段执行的过程中调用或激活另一个阶段。类的加载: 查找并加载类的二进制数据。原创 2024-05-06 05:00:00 · 1080 阅读 · 80 评论 -
Java面试——不安全的集合类
系统性学习,移步Java 中有许多的集合,常用的有List,Set,Queue,Map。其中 List,Set,Queue都是Collection(集合),List中的内容表示其中元素的类型,是泛型的一种使用。不能直接使用简单数据类型做泛型的原因:集合类(比如Set)在进行各种 “操作” ( 如contains()) 时都会调用元素本身提供的 “方法” ( 如hashCode() 和 equals()),而不是由集合类自身去实现这些 “方法”。原创 2024-05-05 05:00:00 · 1348 阅读 · 81 评论 -
多线程模型浅谈
其次,又区别于内核级线程模型,它的进程里的所有线程并不与内核线程一一绑定,而是可以动态绑定同一个内核线程,当某个内核线程因为其绑定的线程的阻塞操作被内核调度出CPU时,其关联的进程中其余用户线程可以重新与其他内核线程绑定运行。:用户线程不内核线程内核线程是一对一(1 : 1)的映射模型,也就是每一个用户线程绑定一个实际的内核线程,而线程的调度则完全交付给操作系统内核去做,应用程序对线程的创建、终止以及同步都基于内核提供的系统调用来完成。内核线程指需要内核的参与,由内核完成线程的调度。的函数来控制用户线程。原创 2024-04-28 05:00:00 · 1998 阅读 · 75 评论 -
ThreadLocal :在 Java中隱匿的魔法之力
ThreadLocal 并不是一个Thread,而是 ThreadLocalVariable(线程局部变量)。也许把它命名为 ThreadLocalVar更加合适。线程局部变量就是为每一个使用该变量的线程都提供一个变量值的副本,是 Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。ThreadLocal是除了加锁这种同步方式之外的另一种保证多线程访问出现线程不安全的方式。原创 2024-03-08 05:00:00 · 8117 阅读 · 103 评论 -
Java 注解机制解密并发编程的时间之谜:揭开Happens-Before的神秘面纱
为什么需要主要是因为Java内存模型, 为了提高CPU效率,通过工作内存Cache代替了主内存。修改这个临界资源会更新但并不一定立刻刷到主存中。通常JMM会将编写的代码编译后执行,在编译器中生成的指令的顺序跟源码的顺序并不是完全一致的。处理器可能采用乱序或者并行的方式来执行指令,因为在JVM中只要程序的最终结果一致,这种重排序是允许的。并且处理器还有本地缓存,当将结果存储在本地缓存中,其他线程是无法看到结果的。除此之外缓存提交到主内存的顺序也肯能会变化。在多线程环境下可能会产生不同的结果。原创 2024-02-22 05:00:00 · 5397 阅读 · 105 评论 -
Java 内存模型深度解析
JSR-133内存模型使用 happens-before的概念来阐述操作之间的内存可见性。JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before关系。这两个操作既可以是同一个线程内,也可以是在不同线程之间。与程序员密切相关的 happens-before规则如下:一个线程中的每个操作,happens-before于该线程中的任意后续操作。对一个锁的解锁,happens-before于随后对这个锁的加锁。原创 2024-01-20 11:30:00 · 3318 阅读 · 48 评论 -
虚拟线程探索与实践
当任务挂载上去之后,就是一个运载线程,执行虚拟线程中的任务。2、由线程池被打满引起的事故很难杜绝,很多应用将核心和非核心的应用一起交由线程池管理;的线程池,减少了线程数量(上面包含了JVM自身的线程和框架的线程);2、虚拟线程:优点是业务侧改造成本低,无需池化,天然隔离。发生了卸载,当链接数耗尽,装载状态的虚拟线程由于拿不到链接被。导致其他获取链接的虚拟线程无运载线程可用。1、由于虚拟线程不需要大量的系统线程调度,节省了。当前线程将任务提交给虚拟线程的时候,是一个。使用虚拟线程后,由于切换了线程,无法从。原创 2024-01-19 11:30:00 · 1371 阅读 · 32 评论 -
Java Reactor Stream
一、Reactor 概念“具有非阻塞负压功能的异步流处理系统” 的标准以及API。1、Reactive Streams 核心接口2、Flux 与 Mono【1】Flux 对象代表一个包含0-N个元素的响应式序列;【2】Mono 对象代表一个包含0-1个元素的响应式序列;3、Reactor 操作符二、Reacotr 基本原理......原创 2022-04-17 23:49:20 · 2274 阅读 · 7 评论 -
AtomicReference 详解
以原子方式更新对象引用,赋值操作不是线程安全的,若不想用锁来实现,可以用AtomicReference这个类。原创 2023-02-13 23:24:04 · 1708 阅读 · 4 评论 -
Java面试——多线程
一、什么是线程线程是指程序在运行的过程中,能够执行程序代码的一个执行单元。Java语言中,线程有四种状态:运行、就绪、挂起、结束二、线程与进程的区别进程是指一段正在执行的程序。而线程有时也被称为轻量级进程,它是程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内存空间(代码段、数据段、堆空间)及一些进程级的文件(列如:打开的文件),但是各个线程拥有自己的栈空间。在操作系统级别上,程序的执行都是以进程为单位的,而每个进程中通常都会有多个线程互不影响地并发执行。三、为什么要使用原创 2021-04-18 14:10:40 · 2186 阅读 · 19 评论 -
Java面试——写一个生产者与消费者
【1】我们可以将生产者和消费者需要的方法写在公共类中package com.yintong.concurrent;import java.util.LinkedList;public class Concurrentcomm { //常量 private static int MAX_VALUE = 10; //可以理解为缓存 LinkedList<String> linkedList = new LinkedList<>();原创 2021-04-18 14:12:18 · 1338 阅读 · 0 评论 -
Java面试——阻塞队列
一、阻塞队列【1】首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下图所示:二、架构分析【1】阻塞队列的架构图:阻塞队列与 List 具有很多类似之处,对比着学习会更加容易一些。【2】阻塞队列重点子类说明: ■ ArrayBlockingQueue:由数组结构组成的有界阻塞队列。 ■ LinkedBlockingQueue:由链表结构组成的有界(大小默认值为 Integer.MAX_VALUE <21亿左右,相当于无界>)阻塞队列。 ■ ......原创 2021-04-18 14:13:23 · 1208 阅读 · 49 评论 -
HashMap 与 ConcurrentHashMap 底层实现
一、HashMap 底层源码JDK7 版本(数组+链表)我们存放的 hashMap 都会封装成一个节点对象 Entry(key,value),然后将此节点对象存放到一个数组中,存放前首先需要确定存放的数组下标:① 通过 hash(key) 算法得到 key 的 hashcode,并通过 hashcode的高16位和低16位进行异或操作(如果两个相应bit位相同,则结果为0,否则为1)得到32位的 int值,首先将高16位无符号右移16位与低十六位做异或运算。如果不这样做,而是直接做&运算(相原创 2021-03-30 22:50:52 · 10658 阅读 · 48 评论 -
ReentrantLock 锁详解
ReentrantLock 锁详解ReentrantLock 支持公平锁和非公平锁,可重入锁 ReentrantLock的底层是通过 **AQS[链接]**实现。一、BAT 大厂的面试题**【1】**什么是可重入,什么是可重入锁? 它用来解决什么问题?【2】ReentrantLock 的核心是 AQS,那么它怎么来实现的,继承吗? 说说其类内部结构关系。【3】ReentrantLock 是如何实现公平锁的?【4】ReentrantLock 是如何实现非公平锁的?【5】ReentrantL原创 2020-12-07 23:27:23 · 95737 阅读 · 18 评论 -
CAS乐观锁(原子操作)
CAS乐观锁(原子操作)锁主要分为两种:乐观锁和悲观锁,而 synchronized 就属于一种悲观锁,每次在操作数据前都会加锁。乐观锁是指:乐观的认为自己在操作数据时,别人不会对当前数据进行修改,因此不会加锁。如果有人对数据进行了修改,则重新获取修改后的数据,进行操作。直到成功为止。而乐观锁的这种机制就是CAS(compare and swap)比较并交换。一、什么是 CASCAS(Compare And Swap | Compare And Set)**:**比较并交换,CAS 是解决多线程原创 2020-12-07 23:26:51 · 1455 阅读 · 32 评论 -
AQS 锁核心类详解
AQS 锁核心类详解AQS(AbstractQuenedSynchronizer 抽象队列同步器) 是一个用来构建锁和同步器的框架,使用 AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于 AQS的。AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。当然,我们自己也能利用 AQS非常轻松容易地原创 2020-12-07 23:26:20 · 1451 阅读 · 1 评论 -
Synchronized 关键字详解
Synchronized 关键字详解Synchronized原理分析加锁和释放锁的原理深入JVM看字节码,创建如下的代码:[](javascript:void(0)????1 public class SynchronizedDemo2 {2 Object object = new Object();3 public void method1() {4 synchronized (object) {5 6 }7 }8 }[]原创 2020-12-07 23:23:29 · 1024 阅读 · 1 评论 -
线程池的实现原理
线程池的实现原理线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数超过了最大数量超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。什么是线程池线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避原创 2020-12-06 23:33:26 · 15152 阅读 · 45 评论 -
线程池的使用
线程池的使用一、常见的五中线程池【1】Executors.newFixedThreadPool(n):创建一个定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待。创建的线程池 corePoolSize 和 maximumPoolSize 值是相等的,使用的是 LinkedBlockingQueue 阻塞队列。执行长期的任务,性能好很多。底层实现如下:public static ExecutorService newFixedThreadPool(int nThreads) { retur原创 2020-12-06 15:19:16 · 1648 阅读 · 81 评论