![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java
文章平均质量分 60
virtuousOne
virtuousOne
展开
-
ConcurrentHashMap源码解析(二)之------put()方法。
当sizeCtl < 0 ,大概率为-1,其他线程正在进行创建table的过程,当前线程没有竞争到初始化table的锁。p是红黑树,如果与你插入节点的key有冲突点的话,则putTreeVal()方法会返回冲突节点的引用。再次判断table为null,防止其他线程已经初始化完毕,然后当前线程再次初始化,导致数据丢失。强制设置binCount为2,因为binCount原创 2023-01-15 11:55:31 · 943 阅读 · 1 评论 -
ConcurrentHashMap源码解析(一)之------基础属性
HashMap在单线程中非常好用,也不会出现什么问题。但是在多线程中,HashTable的效率太低。后面提供了ConcurrentHashMap解决多线程的问题,后续都以1.8的为对象进行研究。在1.8中,ConcurrentHashMap的设计与HashMap保持一致,使用了链表和红黑树的组合,当一个链表上的节点数超过8,且总个数超过64,就会触发转为红黑树。原创 2023-01-08 14:06:00 · 410 阅读 · 0 评论 -
线程池的设计与原理解析(五)之---getTask()方法
1.rs >= SHUTDOWN 成立: 当前的状态最低也是STOP状态,一定要返回 null了。4.线程池中的线程数超过 corePoolSize 时,会有一部分线程可能返回null。getTask()是工作线程在while死循环中获取任务队列中的任务对象的方法;2.前置条件 状态是 SHUTDOWN, workQueue.isEmpty()3.线程池中的线程数量,超过最大限制时,会有一部分线程返回null。1.表示当前线程获取任务是否超时;什么情况下getTask()返回null?原创 2022-12-17 14:40:47 · 768 阅读 · 1 评论 -
线程池的设计与原理解析(四)之---runWorker()方法
2.如果task为空,则通过getTask()再去取任务,并赋值给task,如果取到的Runnable不为空,则执行该任务;在调用start()方法,调用的就是worker的run方法,实际上调用的是runWorker()方法。4.如果getTask()取到的任务依然是空,那么整个runWorker()方法执行完毕;3.执行完毕后,通过while循环继续getTask()取任务。1.如果task不为空,则开始执行task方法。1.将初始执行task赋值给task。简单的梳理runWorker的流程。原创 2022-12-17 14:09:47 · 879 阅读 · 0 评论 -
IDEA常用插件(持续更新中......)
idea好用的插件,推荐插件,最常用的插件原创 2022-12-04 16:35:16 · 3376 阅读 · 0 评论 -
FutureTask详解
FutureTask 表示一个异步运算的任务。FutureTask 里面可以传入一个 Callable 的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。在学习多线程的时候,了解了FutureTask。FutureTask的构造函数。原创 2022-11-19 15:26:30 · 298 阅读 · 0 评论 -
ReentrantLock学习之---释放锁过程
当s==null表示当前节点是tail节点,>0说明当前节点的后继节点是取消状态,说明后继节点是取消状态,需要进行的操作是唤醒一个合适的节点。也可以理解为,释放锁操作在tryRelease()方法中处理,处理完成后,如果不是最后一个节点还会继续唤醒后一个节点的操作。回到release()中,当前的head节点已经被初始化,且后继节点有值,才会进行唤醒后一个节点的操作。在release()方法中,获取成功进入释放锁时,需要的操作是唤醒后继节点的操作.先看tryRelease()方法。...原创 2022-07-24 17:20:05 · 644 阅读 · 0 评论 -
ReentrantLock学习之---基础方法
针对tryAcquire,接下来看下里面的逻辑。本次主要是进入的公平锁的该方法的实现。该方法主要是将线程放入到队列中,再队列中是进行双向绑定,也及为双向链表的结构队列。这里就需要用到上篇博客中的state,获取当前线程的状态进而处理;使用双向链表新加入队列和删除锁的时候双向链表再时间和空间上更节约。另一个逻辑.即为重入锁逻辑,进行更新state的值,每次+1.用了自旋入队的方式,只有当前封装的node成功了才会跳出循环。很明显,加入队列的具体逻辑在enq()方法中。整个线程第一个入队的有一个逻辑....原创 2022-07-23 21:53:56 · 346 阅读 · 0 评论 -
ReentrantLock学习之---基本属性
通过简易的模仿公平锁后,对ReentrantLock的源码进行了学习。waitStatus主要是通过状态判断节点。先对节点Node的属性进行了解。原创 2022-07-17 11:50:58 · 108 阅读 · 0 评论 -
ReentrantLock学习之公平锁过程
ReentrantLock支持公平锁和非公平锁,默认使用非公平锁。Node封装节点,里面包含有前置节点和引用节点和线程信息。在源码中,加公平锁的时候,主要是进行该段代码逻辑获取加锁。在ReentrantLock实现类里面,有几个变量。在公平锁加锁的过程中,还有一段逻辑是获取锁的过程。模拟ReentrantLock的加锁过程。通过源码可以发现公平锁的加锁方法。自定义一个Lock进行实现。主要记录公平锁里面的实现。...原创 2022-07-16 20:05:10 · 482 阅读 · 0 评论 -
Synchronized理论
Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。偏向锁:撤销偏向锁为什么需要在安全点执行?线程获取锁的第一步就是向线程栈的锁记录空间中push一条锁记录信息。并且每次重入,都会插入一条心的锁记录,用于表示重入次数。锁记录空间原则上只允许本线程操作,所以一定是线程安全的。当偏向锁线程依然持有偏向锁时,说明偏向锁线程锁记录空间中一定存在该lock的LockRecord记录。偏向锁撤销,就需要将偏向锁升级为“轻量级锁”。轻量级锁:场景:A和B两个线程,运行过程中获取原创 2022-07-12 10:24:25 · 258 阅读 · 0 评论 -
Netty学习之---Selector
在入门学习netty的时候,我们就写过一个简单client连接service的代码;1:client代码 public static void main(String[] args) throws Exception{ SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("localhost",8080)); System.out.println("waitin原创 2022-05-29 13:15:23 · 345 阅读 · 0 评论 -
Netty之三----java NIO基础
Netty 是基于Java NIO 封装的网络通讯框架,只有充分理解了 Java NIO 才能理解好Netty的底层设计。Java NIO 由三个核心组件组件:BufferChannelSelector一.Channel是一个通道,它就像自来水管一样,网络数据通过 Channel 这根水管读取和写入。传统的 IO 是基于流进行操作的.常见的channel实现类有:1.FileChannel: 读写文本数据 public static void main(String[] args) t原创 2022-05-14 15:38:39 · 156 阅读 · 0 评论 -
Netty之二----源码环境搭建
netty源码环境搭建原创 2022-05-10 21:10:49 · 605 阅读 · 0 评论 -
学习Netty之---Hello Netty
Not faster than NIO (epoll) on unix systems (which is true)There is no daragram suppportUnnecessary threading model (too much abstraction without usage)以上就是Netty目前还是使用NIO的方式的原因;BootStrap: 是Netty框架的启动类和主入口类,分为客户端BootStrap和服务器类ServerBootStrap两种。Channel:原创 2022-05-04 17:33:37 · 680 阅读 · 0 评论 -
深入理解网络通信
今天温习了下之前的网络通信,以及TCP/IP相关的知识。计算机网络的标准定义利用通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来,以功能完善的网络软件及协议实现资源共享和信息传递的系统。OSI七层模型物理层: 网线物理层数据链路层:提供介质访问和链路管理网络层:IP及路由选址传输层:建立和管理端到端的连接会话层:建立会话表示层:数据格式转换、数据加密应用层:为应用程序提供服务TCP/IP 五层模型TCP:一种可靠的数据传输,面向连接。UDP:不可靠原创 2022-04-27 09:35:27 · 1457 阅读 · 0 评论 -
JVM学习之---了解JIT
先对JVM进行一个说明。jvm只识别字节码,所以jvm跟语言是解耦的,jvm运行的是class文件,像Groovy,Kotlin,Scala等语言,他们都可以转移成字节码,也都可以再jvm上运行,这就是JVM的跨语言的特征。解释执行与JIT解释执行:主要是执行字节码指令,一般这些指令会按照顺序解释执行。JIT:在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化。也称为及时编译。(Just In Time Compiler)在JDK10之前(列如jdk8)内置了两个原创 2022-04-12 13:06:58 · 2308 阅读 · 0 评论 -
JVM学习之十---调优实战
Arthas 是阿里巴巴的开源Java诊断工具。Api网址如下https://alibaba.github.io/arthas下载jar包https://arthas.gitee.io/arthas‐boot.jar在Linux中,通过 java -jar就可以运行。打印GC日志方法,在JVM参数里增加参数,%t 代表时间 ‐Xloggc:./gc‐%t.log ‐XX:+PrintGCDetails ‐XX:+PrintGCDateStamps ‐XX:+PrintGCTimeStamps原创 2022-04-11 19:17:44 · 549 阅读 · 0 评论 -
JVM学习之九---调优工具入门
在学习项目调优之前,先对一些基础信息进行学习。通过jps命令,查看进程id.查看堆栈信息jmap -heap 10828导入堆内存到本地jmap -dump:format=b,file=eureka.hprof 10828通过jdk自带的工具进行导入 jvisualvm一:Jstack命令jstack加进程id查找死锁jstack找出占用cpu最高的线程堆栈信息1.使用命令 top -p ,显示Java进程的内存情况。pid 是Java进程号二:Jinfo命令查看郑州原创 2022-04-10 17:11:13 · 3443 阅读 · 0 评论 -
JVM学习之八---垃圾收集器G1
G1收集器(-XX:+UseG1GC)G1(Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高的概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。G1将Java堆划分为多个大小相等的独立区域(Region),jvm最多可以有2018个Region。一般Region大小等于堆大小/2048,比如堆大小为4096M,则Region大小为2M。G1保留了年轻代和老年代的概率,但不再是物理隔阂了,他们都是Region的集合。默认年轻代对堆内存的占原创 2022-04-09 21:50:32 · 1407 阅读 · 0 评论 -
JVM学习之七---底层三色标记算法
垃圾收集底层算法实现三色标记在并发标记的过程中,因为标记期间应用程序还继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。黑色:表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。黑色的对象代表已经扫描过,它是安全存活的,如果有其他对象引用指向了黑色对象,无须重新扫描一遍。黑色对象不可能直接指向某个白色对象。灰色:表示对象已经被垃圾收集器访问过,但这个对象只是存在一个引用还没有被扫描过。白色:表示对象尚未被垃圾收集器访问过。显然在可达性分析刚刚开始的阶段,所有的对象都是原创 2022-04-09 16:04:27 · 435 阅读 · 0 评论 -
JVM学习之六---垃圾收集器
了解垃圾收集器之前,先看下他们的算法。一:垃圾收集算法1.复制算法为了解决效率问题,“复制”收集算法。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就降还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就每次的内存回收都是对内存区间的一半进行回收。2.标记-清除算法算法分为,标记和清除两个阶段:标记存活的对象,统一回收所有未标记的对象.它是最基础的收集算法,比较简单,但是会有两个明显的问题:效率问题(如果需要标记的对象太多,效率不高)空间问题(如果原创 2022-04-09 12:06:05 · 446 阅读 · 0 评论 -
JVM学习之五----字节码文件
今天学习了字节码相关的知识,进行记录一下。一:解读Class文件public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}上边的java文件编译后会生成对应的class文件:Student .class原创 2022-04-05 21:34:59 · 533 阅读 · 0 评论 -
JVM学习之四-----对象内存分配与回收
对象内存分配的流程图如下:对象栈上分配我们通过jvm内存分配可以知道Java中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大的压力,也间接影响了性能。为了减少临时对象在堆内分配的数量,jvm通过逃逸分析确定该对象不会被外部访问。如果不会逃逸可以将该对象在栈上分配内存,这样对象所占用的内存空间可以随栈而销毁,减轻了垃圾回收的压力。对象逃逸:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,列如作为调用参数传原创 2022-04-04 16:53:37 · 292 阅读 · 0 评论 -
JVM学习之三----对象创建
在创建Java对象的过程中,通过代码是new,在内部的执行流程如下一.类加载检查:虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表类是否已被加载、解析和初始化过。如果没有,那么就必须执行相应的类加载过程。二.分配内存:对象所需内存的大小在类加载完成后便可以确定,为对象分配空间的任务等同把一块确定大小的内存从Java堆中划分出来。这个步骤有两个问题,如下:1.如何划分内存。2.在并发情况下, 可能出现正在给对象A分配内存,指原创 2022-04-04 11:55:38 · 1204 阅读 · 0 评论 -
JVM学习之二----整体结构深入了解
在学习JVM的时候,先了解一张整体的结构图和对应的名词。1.堆:存储类实例,一个jvm只有一个堆内存。2.栈(虚拟机栈):存储当前线程运行方法时所需要的数据,指令,返回地址等。3.程序计数器:指向当前线程正在执行的字节码的地址,行号。4.方法区(元空间):存储类信息,常量,运行时常量,静态变量等。5.本地方法栈:同虚拟机栈,不同的是,它存的本地方法的数据。写一个简单的demo程序public class Math { public int compute(){ in原创 2022-03-20 18:38:15 · 178 阅读 · 0 评论 -
JVM指令手册
JVM指令手册栈和局部变量操作将常量压入栈的指令aconst_null 将null对象引用压入栈iconst_m1 将int类型常量-1压入栈iconst_0 将int类型常量0压入栈iconst_1 将int类型常量1压入操作数栈iconst_2 将int类型常量2压入栈iconst_3 将int类型常量3压入栈iconst_4 将int类型常量4压入栈iconst_5 将int类型常量5压入栈lconst_0 将long类型常量0压入栈lconst_1 将long类型常量1压入栈原创 2022-03-20 17:33:12 · 364 阅读 · 0 评论 -
JVM学习之一-----类加载机制
当我们运行一个Java的程序的时候,首先需要通过类加载器把主类加载到JVM中。通过Java命令执行代码的大体流程:一个流程的操作如下图这里主要看类加载器,Java里有如下加载器1.引导类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar,charsets.jar等2.扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包。3.应用程序加载器,负责加载ClassPath路径下的类包,主要是自己写的那些类4.自定义加载器,原创 2022-03-14 11:48:45 · 76 阅读 · 0 评论 -
Java返回封装类
在一个项目开发的过程中,需要使用统一的返回封装对象。这样里面有统一的code, 和对应的message.既方便了后端,也方便前端。1.代码:public class FastResponse<T> implements Serializable { @ApiModelProperty(value = "code编码") private String code; @ApiModelProperty(value = "返回信息") private String原创 2022-01-07 16:58:59 · 1221 阅读 · 0 评论 -
设计模式之----Java责任链模式和建造者模式结合使用
上篇介绍了简单的责任链模式的业务场景和使用,在实际的代码中,可能需要结合多种进行使用才会更好。上篇文章的在service的实现就写的很臃肿,必须指定next,这些在业务场景中都是不能做到很优雅的处理业务。接下来就是对上一篇的责任链模式进行改造,引入建造者模式。建构者模式:建造者设计模式的核心在于隐藏内部构建细节,通过外部的Builder来实现构建。Builder负责Product类对象的具体过程构建,Director负责指导Build,要求Builder按照其指定的顺序去完成Produt的构造。最后原创 2021-11-28 16:13:35 · 1523 阅读 · 1 评论 -
设计模式之----Java责任链模式
最近学习了下责任链模式,进行记录一下。责任链模式:将链中的每一个节点看作一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端出发时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。它属于行为型模式。应用场景:1.多个对象可以处理同一个请求,但是具体由哪个对象处理则在动态中决定。2.在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。让请求和处理 进行解耦。来一个业务场景:用户登录系统,判断用户的角色是否有权限操作。按照之前的原创 2021-11-28 15:54:27 · 452 阅读 · 0 评论 -
设计模式之----Java动态代理模式
在Spring中,有很多设计模式被应用,其中不乏代理模式。而代码模式中,就一定少不了动态代理模式。今天就对动态代理模式进行学习记录。代理模式代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。动态代理:代理类在程序运行时创建的代理方式原创 2021-11-13 20:22:56 · 1422 阅读 · 1 评论 -
ThreadLocal原理解析(二)之---ThreadLocalMap
在了解ThreadLocalMap之前,先了解下Java的弱引用;弱引用的定义:弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存.通过使用弱引用来避免内存泄漏.Product productA = new Product();WeakReference<Product> weakProductA = new WeakReference<>(productA);接下来主原创 2021-09-12 19:24:23 · 544 阅读 · 1 评论 -
ThreadLocal原理解析(一)之---基础属性
最近在学习ThreadLocal相关知识,进行了下记录。一:ThreadLocal是什么?ThreadLocal是服务于Thread的一种本地私有数据机制,threadlocalvariable(线程局部变量), 即为每一个使用该变量的线程都提供一个变量值的副本,与使用的线程绑定,每一个线程都可以独立地改变自己的副本,不会产生冲突。 其在Thread处于活跃状态,并且threadLocal对象可用的情况下,就可以在其中存放数据。在线程被销毁之后,则ThreadLocal中使用的资源和内存同时也被回收。本原创 2021-09-11 22:51:05 · 260 阅读 · 0 评论 -
AQS重入锁原理解析(一)之---基础属性
在学习JUC下包的时候,必然会学习到Lock,同时就会了解到ReentrantLock,而当我们深入了解ReentrantLock锁原理的时候,就会发现它实现了AbstractQueuedSynchronizer的功能,也就是简称的AQS。今天就先从里层到外层的学习,先学习AQS的一些原理属性相关知识。一:什么是AQSAbstractQueuedSynchronizer,抽象队列同步器。简称AQS。是JDK提供的,位于J.U.C locks包下的一个抽象类,相当于提供了一个模板,实现让线程排队访问资源的原创 2021-08-29 14:35:23 · 310 阅读 · 0 评论 -
JAVA开发小技巧之----返回封装类
在也代码开发的过程中,我们一般都会封装一个对象,进行统一的返回给前端,常见的其中包含code, msg,data这些值。之前常用的一个返回封装类:public class ResponseClass<T> { private String code; private String msg; private T data; public ResponseClass(){ } public ResponseClass(T data, Stri原创 2021-08-23 22:23:34 · 1393 阅读 · 0 评论 -
线程池的设计与原理解析(三)之---addWorker()方法
在线程池方法中,有个重要的方法就是添加线程。也就是我们接下来要描述的addWorker()方法.该方法主要做两个事情:1).使用循环CAS操作来讲线程池的数量+1;2).新建一个线程worker,添加到workers中并启用。该方法中会传入两个参数,第一个是直接传入任务实列,第二个参数标识是否是核心线程。接下来就主要关注这个方法的源码1.该方法是个boolean返回的方法; 如果返回ture:表示创建worker成功,且线程启动成功;如果返回false :表示创建worker失败;导致fals原创 2021-08-22 13:23:22 · 1282 阅读 · 2 评论 -
线程池的设计与原理解析(二)之---execute()方法
在使用线程池的时候,我们会使用到提交线程池的方法execute()。 public void execute(Runnable command) { e.execute(command); }它的主要作用是提交执行任务,参数支持Runnable, execute()没有返回值,同时,它的任务里必须捕获异常。execute()的工作主要流程如下图所示:接下来就主要去看看这个execute()方法的源码含义1.当传入一个 null的 Runnable的时候,会进行抛出异常 if (co原创 2021-08-22 10:30:27 · 1718 阅读 · 0 评论 -
线程池的设计与原理解析(一)之---基础入门
什么是线程池在 Java 中,如果每个请求到达就创建一个新线程,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。如果在一个 Jvm 里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足为了解决这个问题,就有了线程池的概念,线程池的核心逻辑是提前创建好若干个线程放在一个容器中。如果有任务需要处理,则将任务直接分配给线程池中的线程来执行就行,任务处理完以后这个线程不会被销毁,而是等待后续分配任务。同时通过线程池来重复原创 2021-08-21 16:51:36 · 167 阅读 · 0 评论 -
jdk1.8中对ConcurrentHashMap的理解(三)
上一篇博客中,了解了put方法,结尾的时候,有addCount()方法,今天继续学习。 在map中,容易出现线程安全的,除了put()方法的操作,另一个就是map的扩容机制。 接下来就深入理解concurrentHashMap中的的扩容机制。 在调用addCount()方法的时候,会涉及到transfer()方法的调用,而该方法就是我们今天要深入学习的扩容方法。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f345221552274705a99f1f9470e97原创 2021-08-21 00:42:41 · 190 阅读 · 0 评论