自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(343)
  • 资源 (3)
  • 收藏
  • 关注

原创 随手笔记(五十三)Claude code升级项目JDK8到11

最重要的是,我用的第一个AI工具,kilo code就是VS的小寄生虫,感觉很好用,最关键的是配置内容清晰可见,不需要太多研究,既可以使用API和base_url又可以无痛配置MCP Server。但是他对于Java就有些相形见绌了,我让他写功能接口,他可以非常迅速的生成,但是写的XML语句全都落在的Mapper标签的最后面,不符合语法规范。不得不说,费尽心思安装的Claude code完美的解决了我AI小工具的问题,之前我为了找小工具,特意安装了万能的IDE:VS code。

2025-11-24 14:45:17 346

原创 随手笔记(五十二)Docker弃用OpenJDK,如何处理

略微尴尬的是,这个镜像打上去可以,结果我项目里的一个lib下jar包,报了centOs 缺失的错误,看来这个镜像不太行。我项目之前的镜像引入的是OpenJDK,但是他现在弃用了,这就很尴尬。

2025-11-24 14:36:59 267

原创 干货--并发编程提高-为什么wait()方法要放在同步块中(三十六)

虽然在java语言规范和java内存模型中都没有给出不可变性的正式定义,但不可变性并不等于将所有对象中的域都声明为final类型,即使对象中所有域都是final类型的,这个对象仍然是可变的。2.只读共享:在没有额外同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它,共享的只读对象包括不可变对象和事实不可变对象。4.保护对象:被保护的对象只能通过持有特定的锁来访问,保护对象包括封装在其他线程安全对象中的对象,以及已发布的并且由某个特定锁保护的对象。3.对象是正确的创建的。

2025-11-12 11:46:05 289

原创 干货--并发编程提高-为什么wait()方法要放在同步块中(三十五)

java语言提供了一种稍弱的同步机制,即voliate变量,用来确保将变量的更新操作通知到其他线程,当把变量声明为voliate时,编译器与运行时都会注意到这个变量是共享的,因为在编译器期不会将该变量上的操作与其他内存操作一起重排序,voliate变量不会被缓存在寄存器或者对其他处理器不可见的地方,因为在读取voliate类型的变量时总是会返回最新写入的值。所有的处理器都会缓存一部分数据用于高效的计算,然后voliate声明的类无法缓存在寄存器中,这使得该变量对各个线程是可见的,是同步的。

2025-11-12 11:46:00 834

原创 并发编程案例分析——高性能网络应用框架Netty(四十七)

利用非阻塞式 API 就能够实现一个线程处理多个连接,现在普遍都是采用 Reactor 模式,包括 Netty 的实现。网络编程性能的瓶颈(BIO)Netty 中的线程模型。Reactor 模式。

2025-10-24 15:28:02 964

原创 并发编程案例分析——高性能限流器Guava RateLimiter(四十六)

Guava RateLimiter通过令牌桶算法实现高并发限流,核心机制是定时生成令牌并控制获取。令牌桶包含容量、生成间隔等参数,通过预占令牌和动态计算桶中令牌数来精确控制流量。相比自行实现的方案,它避免了定时器精度问题。除标准功能外,还支持预热机制,通过积分函数动态调整流速。该工具适用于系统保护、缓存预热等场景,是处理突发流量的有效方案。

2025-10-24 13:36:30 906

原创 并发编程设计模式——生产者-消费者模式(四十五)

概述:生产者 - 消费者模式的核心是一个任务队列,生产者线程生产任务,并将任务添加到任务队列中,而消费者线程从任务队列中获取任务并执行。Java 线程不是越多越好,适量即可。而生产者 - 消费者模式恰好能支持你用适量的线程。支持异步,并且能够平衡生产者和消费者的速度差异(任务队列出力了)解耦,减少代码或组件之间的依赖关系。生产者 - 消费者模式的优点。支持分阶段提交以提升性能。支持批量执行以提升性能。

2025-06-23 07:45:00 810

原创 并发编程设计模式——两阶段终止模式模式(四十四)

标答:当线程的run方法中执行业务逻辑时候调用到第三方类库提供的方法,保不准第三方类库在捕获到异常时,不会重置interrupt标志位。导致线程的中断状态被清空,造成影响。建议自己实现一个线程终止标志位,这样即使调用第三方方法也不会影响到自定义的线程中止标志位。两阶段终止模式需要注意两个关注点,一个是仅检查终止标志位是不够的,因为线程的状态可能处于休眠状态;另一个就是仅检查线程的中断状态也是不够的,因为我们依赖的第三方类库很可能没有正确的处理中断异常。案例:用两阶段终止模式终止监控操作。

2025-06-23 07:00:00 322

原创 干货--并发编程提高-线程池要点(三十三)

"数据竞争"术语很容易与另外一个相关术语"竞态条件"混淆,"数据竞争"是指,如果在访问共享的非final类型的域时没有采用同步来进行协调,那么就会出现数据竞争,当一个数据写入一个变量而另一个线程接下来读取这个变量,或者读取一个之前由另一个线程写入的变量时,并且在这两个线程之间没有使用同步,那么就可能出现数据竞争。竞态条件出现的场景:比较经典的场景就是单例模式,单例模式首先判断对象是否初始化,如果没有则初始化,并创建一个新的对象并返回一个引用,从而在后台的调用中无须再执行这段高开销的代码。

2025-03-31 14:52:38 494

原创 干货--并发编程提高-线程池痛点(三十二)

也就是说当future的状态>COMPLETING时候调用get方法才会返回,而明显DiscardPolicy策略在拒绝元素的时候并没有设置该future的状态,后面也没有其他机会可以设置该future的状态,所以future的状态一直是NEW,所以一直不会返回,同理DiscardOldestPolicy策略也是这样的问题,最老的任务被淘汰时候没有设置被淘汰任务对于future的状态,也会导致一直不会返回。线程池被创建后如果没有任务过来,里面是不会有线程的。线程池被创建后里面有线程吗?

2025-03-31 14:50:14 539

原创 并发编程设计模式——Worker Thread模式(四十三)

案例承继自上一章echo服务端案例:相比于 Thread-Per-Message 模式的实现,改动非常少,仅仅是创建了一个最多线程数为 500 的线程池 es,然后通过 es.execute() 方法将请求处理的任务提交给线程池处理。优势:可以避免无限制的创建线程导致OOM;并且可以避免无限制的接收任务导致OOM。Worker Thread模式及其实现。如何避免重复创建线程?

2025-02-12 08:15:00 431

原创 并发编程设计模式——Thread-Per-Message模式(四十二)

Thread-Per-Message模式:为每个任务分配一个独立的线程。经典应用:网络编程里服务端的实现(服务端为每个客户端请求创建一个独立的线程,当线程处理完请求后,自动销毁)。用 Thread 实现 Thread-Per-Message 模式(这个实现用于对比,很坑)如何理解 Thread-Per-Message 模式(委托代办)Fiber 实现 Thread-Per-Message 模式。最简单实用的分工方法。

2025-02-12 07:45:00 307

原创 干货--并发编程提高-线程池实施设置参数的痛点(三十一)

对于当前值小于当前工作线程数的情况,说明有多余的worker线程,此时会向当前idle的worker线程发起中断请求以实现回收,多余的worker在下次idel的时候也会被回收;对于包含I/O操作或其他阻塞操作的任务,由于线程不会一直执行,因此线程池的规模应该更大,要正确地设置线程池的大小,需估算出任务的等待时间与计算时间的比值,这种估算不需要很精确。可以把它当做一个备份线程就好。而且,你再品一品 JDK 的源码,其实源码也体现出了有修改的含义的,两个值去做差值,只是第一次设置的时候原来的值为 0 而已。

2024-12-17 08:30:00 471

原创 干货--并发编程提高-线程池拒绝策略-补充(三十)

也就是说当future的状态>COMPLETING时候调用get方法才会返回,而明显DiscardPolicy策略在拒绝元素的时候并没有设置该future的状态,后面也没有其他机会可以设置该future的状态,所以future的状态一直是NEW,所以一直不会返回,同理DiscardOldestPolicy策略也是这样的问题,最老的任务被淘汰时候没有设置被淘汰任务对于future的状态,也会导致一直不会返回。运行后发现程序能正常退出。那么默认的AbortPolicy策略为啥没问题那?

2024-12-17 08:00:00 367

原创 干货--并发编程提高-线程池拒绝策略(二十九)

从运行结果看在任务one阻塞的5s内,主线程执行到了代码(5)等待任务one执行完毕,当任务one执行完毕后代码(5)返回,主线程打印出task one finish null。之后线程池的唯一线程会去队列里面取出任务two并执行所以输出start runable two然后代码(6)会返回,这时候主线程输出task two finish null,然后执行代码(7)等待任务three执行完毕,从执行结果看代码(7)会一直阻塞不会返回。再向线程池提交了一个任务two,这时候会把任务two放入到阻塞队列;

2024-12-12 08:30:00 466

原创 干货--并发编程提高-线程池预热(二十八)

线程池被创建后如果没有任务过来,里面是不会有线程的。allowCoreThreadTimeOut 该值默认为 false。核心线程数会被回收吗?

2024-12-12 08:00:00 305

原创 干货--并发编程提高-线程池的阻塞队列和工作流程(二十七)

2024-12-02 08:15:00 129

原创 干货--并发编程提高-死锁怎么避免续(二十六)

前面我们提到第一个Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。这个线程也是在main线程之后创建的,其优先级为10,主要用于在垃圾收集前,调用对象的finalize()方法;该线程也是daemon线程,因此如果虚拟机中没有其他非daemon线程,不管该线程有没有执行完finalize()方法,JVM也会退出;只有当开始一轮垃圾收集时,才会开始调用finalize()方法;

2024-12-02 08:00:00 197

原创 干货--并发编程提高-死锁怎么避免(二十五)

还有一种方式,破坏循环等待方式,破坏这个条件,需要对资源进行排序,然后按序申请资源。这个实现非常简单,我们假设每个账户都有不同的属性 id,这个 id 可以作为排序字段,申请的时候,我们可以按照从小到大的顺序来申请。4.循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。2.占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;必须同时获取到XY两个资源,才能进行同步,这样便解决了循环依赖等待的情况。

2024-11-27 08:30:00 462

原创 干货--并发编程提高-关闭线程池(二十四)

最后,一定要记得,shutdownNow和shuwdown调用完,线程池并不是立马就关闭了,要想等待线程池关闭,还需调用awaitTermination方法来阻塞等待。如果线程池阻塞等待从队列里读取任务,则会被唤醒,但是会继续判断队列是否为空,如果不为空会继续从队列里读取任务,为空则线程退出。shutdownNow方法的解释是:线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。shutdown方法的解释是:线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。

2024-11-27 08:00:00 405

原创 并发编程设计模式——Copy-On-Write模式(四十一)

Java 提供了 CopyOnWriteArrayList,为什么没有提供 CopyOnWriteLinkedList 呢?Copy-on-Write 模式的应用领域。

2024-11-14 08:30:00 552

原创 并发编程设计模式——Immutability模式(四十)

问题:如果具备不可变性的类,需要提供类似修改的功能,创建一个新的不可变对象就行了,这是与可变对象的一个重要区别,可变对象往往是修改自己的属性。所有的修改操作都创建一个新的不可变对象:这样会不会造成创建的对象太多了,有点太浪费内存呢?Foo 具备不可变性,线程安全,但是类 Bar 并不是线程安全的,类 Bar 中持有对 Foo 的引用 foo,对 foo 这个引用的修改在多线程中并不能保证可见性和原子性。本意是 A 用锁 al,B 用锁 bl,各自管理各自的,互不影响。快速实现具备不可变性的类。

2024-11-14 08:15:00 873

原创 并发编程设计模式——Balking模式(三十九)

多线程下,维护一个共享状态满足某个条件时,执行业务逻辑;当不满足时则立即放弃。通常用互斥锁来确保共享状态线程安全,如果不需要保证共享状态原子性,也可以用 volitle 修饰,替换互斥锁。Balking 模式本质上是一种规范化地解决“多线程版本的 if”的方案,其实就是对if判断的加锁设计。并抽象一个方法出来。使用 volatile 的前提是对原子性没有要求。用 volatile 实现 Balking 模式。Balking 模式的经典实现。这样的好处是将并发处理逻辑和业务逻辑分开。Balking 模式。

2024-11-11 08:30:00 539

原创 并发编程设计模式——Guarded Suspension模式(三十八)

概述:多线程下,A线程有个受保护的操作,在执行过程中需要等待满足某个条件,这个条件由B线程控制,条件不满足,A线程则挂起,直到条件满足才继续执行。例子:核心是:get() 方法通过条件变量的 await() 方法实现等待,onChanged() 方法通过条件变量的 signalAll() 方法实现唤醒功能。单线程场景中,if 语句是不需要等待的,因为在只有一个线程的条件下,如果这个线程被阻塞,那就没有其他活动线程了,这意味着 if 判断条件的结果也不会发生变化了。”来理解这个模式会更简单。

2024-11-11 08:15:00 315

原创 干货--并发编程提高-配置线程池(二十三)

1.任务性质不同的任务可以用不同规模的线程池分开处理,程序密集型任务尽量配置少的线程数量,入Ncpu+1的线程,Ncpu是cpu核心数。混合任务,如果可以拆分,拆分成一个程序密集型任务和一个io密集型任务,只要两任务的执行时间不是相差太大,拆分后的吞吐率更高,用各自的线程池去做;4.依赖数据库连接的任务,因为线程提交sql后需要等待数据库返回执行结果(数据库io,数据网络传输),如果时间越长,cpu空闲时间越长,此线程堵塞时间越长,那么就应该设置更多的线程,充分利用cpu。3.任务的执行时间:长、中、短。

2024-11-01 08:30:00 261

原创 干货--并发编程提高-计算CPU利用率(二十二)

输出解释 CPU以及CPU0、CPU1、CPU2、CPU3每行的每个参数意思(以第一行为例)为: 参数解释 user (432661) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies),不包含nice值为负的进程。“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;它的单位随硬件平台的不同而不同。在Linux/Unix下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。

2024-11-01 08:00:00 853

原创 干货--并发编程提高-CPU 使用率低高负载的原因-下(二十一)

上面说过,cpu的工作效率要高于磁盘,而进程在cpu上面运行需要访问磁盘文件,这个时候cpu会向内核发起调用文件的请求,让内核去磁盘取文件,这个时候会切换到其他进程或者空闲,这个任务就会转换为不可中断睡眠状态。当在数据特别大的时候,如果执行的sql语句没有索引,就会造成扫描表的行数过大导致I/O阻塞,或者是语句中存在死锁,也会造成I/O阻塞,从而导致不可中断睡眠进程过多,导致负载过大。在上面的进程状态变换过程中,除了running状态,其他都是等待状态,那么其他状态都会加入到负载等待进程中吗?

2024-10-25 08:45:00 661

原创 干货--并发编程提高-CPU 使用率低高负载的原因-上(二十)

产生的原因一句话总结就是:等待磁盘I/O完成的进程过多,导致进程队列长度过大,但是cpu运行的进程却很少,这样就体现到负载过大了,cpu使用率低。下面内容是具体的原理分析:在分析负载为什么高之前先介绍下什么是负载、多任务操作系统、进程调度等相关概念。什么是负载:负载就是cpu在一段时间内正在处理以及等待cpu处理的进程数之和的统计信息,也就是cpu使用队列的长度统计信息,这个数字越小越好(如果超过CPU核心*0.7就是不正常)负载分为两大部分:CPU负载、IO负载。

2024-10-25 08:00:00 1023

原创 干货--并发编程提高-线程池三问(十九)

如果我们需要处理的是一个长连接,即个连接上都是一个执行时间很长的任务,甚至就是一个不会停止的任务,这样我们就没有必要使用线程池技术。最后,一定要记得,shutdownNow和shuwdown调用完,线程池并不是立马就关闭了,要想等待线程池关闭,还需调用awaitTermination方法来阻塞等待。shutdownNow方法的解释是:线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。shutdown方法的解释是:线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。

2024-10-24 08:45:00 782

原创 干货--并发编程提高-Condition(十八)

原因是:当未分配会员较多时,可能需要5秒才能分配完,然而executor.submit是异步操作,当休眠1秒钟后,马上又进入下一个循环,队列里又将插入重复的会员,这会导致队列长度不断增长,此外,会导致1个会员被分配后,又继续被分配,导致异常产生。这个问题我综合下来看,感觉还是不是很优雅,到不如这样设计感觉很有问题,当然我是站在了我的角度,可能没有业务的束缚,我感觉这种形式可以使用MQ来解决,可以一次发一批次的数据来处理,MQ天然的幂等性就能解决重新分配的问题,也无需自旋写个死循环来处理。

2024-10-24 08:15:00 730

原创 干货--并发编程提高-ReentrantLock(十六)

如果没有成功,则进入acquire方法以进一步获取锁,公平锁则是直接进入acquire方法。在Lock方法执行的时候非公平锁是先CAS尝试获取锁,未获取到后进入尝试获取锁,紧接着如果发现此时锁已释放又CAS尝试获取锁,如果两次都没有则跟公平锁一样进入等待队列。公平锁此时会判断内部维持的队列是否轮到了自己参考上图,如果轮到自己才会CAS尝试获取锁,修改成功了,则将当前线程设置为独占线程并返回。非公平锁就是当占用锁的线程释放锁时,所有等待的线程都会竞争锁。默认是非公平锁,可选参数配置是否公平锁。

2024-10-23 08:45:00 1048

原创 干货--并发编程提高-硬件同步原语-CAS&FAA(十五)

只能看当前操作系统是否支持了,很类似于NIO中的非阻塞算法,优先考虑使用更高效的,实在没得选再使用select方法一样。如果CAS更新失败了,则说明有其他线程也在更新此值,此时线程不阻塞,而是不停的尝试更新,直到成功。语义:先获取变量p当前的值value,然后给变量p增加inc (值),最后返回变量p之前的值。此操作也是原子性操作,FAA的性能要优于CAS,但FAA仅限于简单的加减法。因其CAS的原理,所以产生了ABA的问题。此外,lock-free作用于单个变量,导致大部分基于CAS的实现都比较复杂。

2024-10-23 08:30:00 606

原创 并发编程工具集——Fork/Join-下(三十七)

这个共享的 ForkJoinPool 默认的线程数是 CPU 的核数。用 Fork/Join 计算斐波那契数列。模拟 MapReduce 统计单词数量。ForkJoinPool 工作原理。

2024-09-26 10:18:02 830

原创 我的创作纪念日-干货-并发编程提高——Synchronized&AQS(十四)

及一些列私有的操作。如果是单核处理器,不建议使用自旋锁。在于当一个在等待队列中的共享节点成功获取到锁以后(它获取到的是共享锁),既然是共享,那它必须要依次唤醒后面所有可以跟它一起共享当前锁资源的节点,毫无疑问,这些节点必须也是在等待共享锁(这是大前提,如果等待的是独占锁,那前面已经有一个共享节点获取锁了,它肯定是获取不到的)。跟独占锁相比,共享锁的。自旋是一种非阻塞锁,也就是说,如果某线程需要获取锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取自旋锁。

2024-09-26 10:16:30 785

原创 并发编程工具集——Fork/Join-上(三十六)

Fork/Join 的使用。

2024-09-24 08:00:00 478

原创 并发编程工具集——CompletionService(三十五)

例如你需要提供一个地址转坐标的服务,为了保证该服务的高可用和性能,你可以并行地调用 3 个地图服务商的 API,然后只要有 1 个正确返回了结果 r,那么地址转坐标这个服务就可以直接返回 r 了。通过调用 cs.take().get(),我们能够拿到最快返回的任务执行结果,只要我们拿到一个正确返回的结果,就可以取消所有任务并且返回最终结果了。Dubbo 中有一种叫做 Forking 的集群模式,这种集群模式下,支持并行地调用多个查询服务,只要有一个成功返回结果,整个服务就可以返回了。

2024-09-24 07:15:00 1693

原创 干货-并发编程提高——重谈 RUNNABLE-下篇(十五)

cpu 与硬盘间是并发的。如果把线程视作为一个 job,这一 job 由 cpu 与硬盘交替协作完成,当在 cpu 上是 waiting 时,在硬盘上却处于 running,只是我们在操作系统层面讨论线程状态时通常是围绕着 cpu 这一中心去述说的。如果让 cpu 去等 I/O 的操作,很可能时间片都用完了,I/O 操作还没完成呢,不管怎样,它会导致 cpu 的利用率极低。至少我们看到了,进行传统上的 IO 操作时,口语上我们也会说 “阻塞”,但这个 “阻塞” 与线程的 BLOCKED 状态是两码事!

2024-09-19 08:30:00 739

原创 干货-并发编程提高——重谈 RUNNABLE-上篇(十四)

直接看它的 Javadoc 中的说明:一个在 JVM 中执行的线程处于这一状态中。(A threadexecuting而传统的进(线)程状态一般划分如下:注:这里的进程指早期的单线程进程,这里所谓进程状态实质就是线程状态。那么 runnable 与图中的 ready 与 running 区别在哪呢?

2024-09-19 08:00:00 1104

原创 并发编程工具集——CompletionStage (三十四)

CompletionStage 接口里面描述 AND 汇聚关系,主要是 thenCombine、thenAcceptBoth 和 runAfterBoth 系列的接口,这些接口的区别也是源自 fn、consumer、action 这三个核心参数不同。applyToEither、acceptEither 和 runAfterEither。描述 AND 汇聚关系。都是靠回调函数来解决的。描述 OR 汇聚关系。

2024-09-02 08:30:00 1063

原创 并发编程工具集——CompletableFuture(三十三)

前两个方法:runAsync(Runnable runnable)和supplyAsync(Supplier<U> supplier),它们之间的区别是:Runnable 接口的 run() 方法没有返回值,而 Supplier 接口的 get() 方法是有返回值的。CompletableFuture 的核心优势。如何理解 CompletionStage 接口。

2024-09-02 08:00:00 526

apache-zookeeper-3.7.0-bin.tar.gz

apache-zookeeper-3.7.0-bin.tar.gz

2022-01-04

canal-master.zip

canal

2022-01-04

Redis数据结构与对象总结

Redis数据结构与对象总结 数据结构与对象 简单动态字符串 SDS简介 SDS与C字符串的区别 常数复杂度获取字符串长度 O(n) O(1) 杜绝缓冲区溢出 修改字符串长度时内存重分配 空间预分配:对字符串进行增长操作时的优化,SDS API 会检查SDS当前空间是否符合修改条件,如果不符合 不但会分配修改所需空间还会分配给free属性额外的未使用空间 惰性空间释放:对字符串进行缩减操作时

2020-04-24

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除