博客园 - 路仁甲
uuid:24b78886-0ed1-41c2-8670-e3f31dcf42c4;id=12939
2022-03-23T08:32:19Z
路仁甲
https://www.cnblogs.com/lusaisai/
feed.cnblogs.com
https://www.cnblogs.com/lusaisai/p/15983313.html
15-并发设计模式 - 路仁甲
并发(多线程)设计模式不同于传统设计模式,更关注的是并发编程中特定场景的解决方案。对于并发设计模式同学们务必理解。 终止线程的设计模式 思考:在一个线程 T1 中如何正确安全的终止线程 T2? 错误思路1:使用线程对象的 stop() 方法停止线程 stop 方法会真正杀死线程,如果这时线程锁住了共
2022-03-08T16:41:00Z
2022-03-08T16:41:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】并发(多线程)设计模式不同于传统设计模式,更关注的是并发编程中特定场景的解决方案。对于并发设计模式同学们务必理解。 终止线程的设计模式 思考:在一个线程 T1 中如何正确安全的终止线程 T2? 错误思路1:使用线程对象的 stop() 方法停止线程 stop 方法会真正杀死线程,如果这时线程锁住了共 <a href="https://www.cnblogs.com/lusaisai/p/15983313.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983310.html
14-Future&CompletableFuture - 路仁甲
Callable&Future&FutureTask 直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Ca
2022-03-08T16:38:00Z
2022-03-08T16:38:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Callable&Future&FutureTask 直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Ca <a href="https://www.cnblogs.com/lusaisai/p/15983310.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983305.html
13-高性能内存队列Disruptor - 路仁甲
Disruptor简介 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了业界关注。2011年,企业
2022-03-08T16:35:00Z
2022-03-08T16:35:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Disruptor简介 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了业界关注。2011年,企业 <a href="https://www.cnblogs.com/lusaisai/p/15983305.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983298.html
12-ForkJoin - 路仁甲
任务类型 思考: 线程池的线程数设置多少合适? 我们调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能。在实际工作中,我们需要根据任务类型的不同选择对应的策略。 CPU密集型任务 CPU密集型任务也叫计算密集型任务,比如加密、解密、压缩、计
2022-03-08T16:33:00Z
2022-03-08T16:33:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】任务类型 思考: 线程池的线程数设置多少合适? 我们调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能。在实际工作中,我们需要根据任务类型的不同选择对应的策略。 CPU密集型任务 CPU密集型任务也叫计算密集型任务,比如加密、解密、压缩、计 <a href="https://www.cnblogs.com/lusaisai/p/15983298.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983289.html
11-阻塞队列BlockingQueue - 路仁甲
阻塞队列介绍 Queue接口 public interface Queue<E> extends Collection<E> { //添加一个元素,添加成功返回true, 如果队列满了,就会抛出异常 boolean add(E e); //添加一个元素,添加成功返回true, 如果队列满了,返回fa
2022-03-08T16:30:00Z
2022-03-08T16:30:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】阻塞队列介绍 Queue接口 public interface Queue<E> extends Collection<E> { //添加一个元素,添加成功返回true, 如果队列满了,就会抛出异常 boolean add(E e); //添加一个元素,添加成功返回true, 如果队列满了,返回fa <a href="https://www.cnblogs.com/lusaisai/p/15983289.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983281.html
10-AQS之ReentrantReadWriteLock - 路仁甲
读写锁 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发);但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读,
2022-03-08T16:26:00Z
2022-03-08T16:26:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】读写锁 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发);但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读, <a href="https://www.cnblogs.com/lusaisai/p/15983281.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983276.html
09-Semaphorer&CountDownLatch&CyclicBarrie - 路仁甲
Semaphore Semaphore介绍 Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于AbstractQueuedSynchronizer实现的。 Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获取信号量实现。大
2022-03-08T16:23:00Z
2022-03-08T16:23:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Semaphore Semaphore介绍 Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于AbstractQueuedSynchronizer实现的。 Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获取信号量实现。大 <a href="https://www.cnblogs.com/lusaisai/p/15983276.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983272.html
08-AQS之ReentrantLock - 路仁甲
AQS原理分析 什么是AQS java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现
2022-03-08T16:21:00Z
2022-03-08T16:21:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】AQS原理分析 什么是AQS java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现 <a href="https://www.cnblogs.com/lusaisai/p/15983272.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983265.html
07-深入理解synchronized - 路仁甲
Java共享内存模型带来的线程安全问题 思考: 两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗? @Slf4j public class SyncDemo { private static volatile int counter = 0; public
2022-03-08T16:17:00Z
2022-03-08T16:17:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Java共享内存模型带来的线程安全问题 思考: 两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗? @Slf4j public class SyncDemo { private static volatile int counter = 0; public <a href="https://www.cnblogs.com/lusaisai/p/15983265.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983242.html
06-Atomic原子操作类详解 - 路仁甲
Atomic原子操作类介绍 在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更新变量i=1,比如多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程安全的目的。但是由于synchronized是采用的是悲观锁策略
2022-03-08T16:06:00Z
2022-03-08T16:06:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Atomic原子操作类介绍 在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更新变量i=1,比如多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程安全的目的。但是由于synchronized是采用的是悲观锁策略 <a href="https://www.cnblogs.com/lusaisai/p/15983242.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983231.html
05-深入理解CAS - 路仁甲
什么是 CAS CAS(Compare And Swap,比较并交换),通常指的是这样一种原子操作:针对一个变量,首先比较它的内存值与某个期望值是否相同,如果相同,就给它赋一个新值。 CAS 的逻辑用伪代码描述如下: if (value == expectedValue) { value = new
2022-03-08T16:04:00Z
2022-03-08T16:04:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】什么是 CAS CAS(Compare And Swap,比较并交换),通常指的是这样一种原子操作:针对一个变量,首先比较它的内存值与某个期望值是否相同,如果相同,就给它赋一个新值。 CAS 的逻辑用伪代码描述如下: if (value == expectedValue) { value = new <a href="https://www.cnblogs.com/lusaisai/p/15983231.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983227.html
04-深入理解Java线程 - 路仁甲
线程基础知识 线程和进程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中 还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 。 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程
2022-03-08T16:02:00Z
2022-03-08T16:02:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】线程基础知识 线程和进程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中 还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 。 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程 <a href="https://www.cnblogs.com/lusaisai/p/15983227.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983204.html
03-Java并发线程池 - 路仁甲
线程池与线程对比: 线程方式 import java.util.ArrayList; import java.util.List; import java.util.Random; /*** * 使用线程的方式去执行程序 */ public class ThreadTest { public sta
2022-03-08T15:54:00Z
2022-03-08T15:54:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】线程池与线程对比: 线程方式 import java.util.ArrayList; import java.util.List; import java.util.Random; /*** * 使用线程的方式去执行程序 */ public class ThreadTest { public sta <a href="https://www.cnblogs.com/lusaisai/p/15983204.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983195.html
02-并发的三大特性和volatile - 路仁甲
并发和并行 目标都是最大化CPU的使用率 并行(parallel): 指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。 并发(concurrency): 指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时
2022-03-08T15:51:00Z
2022-03-08T15:51:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】并发和并行 目标都是最大化CPU的使用率 并行(parallel): 指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。 并发(concurrency): 指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时 <a href="https://www.cnblogs.com/lusaisai/p/15983195.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983180.html
01-CPU缓存架构&缓存一致性协议 - 路仁甲
CPU高速缓存(Cache Memory) CPU高速缓存 CPU缓存即高速缓冲存储器,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据
2022-03-08T15:47:00Z
2022-03-08T15:47:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】CPU高速缓存(Cache Memory) CPU高速缓存 CPU缓存即高速缓冲存储器,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据 <a href="https://www.cnblogs.com/lusaisai/p/15983180.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983159.html
02-SpringBoot启动原理 - 路仁甲
SpringBoot启动流程: 调用SpringApplication.run启动springboot应用 public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args);
2022-03-08T15:40:00Z
2022-03-08T15:40:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】SpringBoot启动流程: 调用SpringApplication.run启动springboot应用 public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args); <a href="https://www.cnblogs.com/lusaisai/p/15983159.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983132.html
01-springboot自动装配原理 - 路仁甲
Springboot自动装配原理详解 传统配置 1)传统ssm整合redis的时候 需要在xml的配置文件中 进行大量的配置Bean 第一步:加入依赖 <dependency> <groupId>org.springframework.data</groupId> <artifactId>sprin
2022-03-08T15:33:00Z
2022-03-08T15:33:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Springboot自动装配原理详解 传统配置 1)传统ssm整合redis的时候 需要在xml的配置文件中 进行大量的配置Bean 第一步:加入依赖 <dependency> <groupId>org.springframework.data</groupId> <artifactId>sprin <a href="https://www.cnblogs.com/lusaisai/p/15983132.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983121.html
04-SpringMVC之请求处理流程 - 路仁甲
SpringMVC之请求处理流程 我们知道DispatcherServlet就是一个HttpServlet,而HttpServlet的请求就从doGet/doPost开始 DispatcherServlet本身没有实现doGet/doPost,而由他的父类FrameworkServlet实现,源码如
2022-03-08T15:31:00Z
2022-03-08T15:31:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】SpringMVC之请求处理流程 我们知道DispatcherServlet就是一个HttpServlet,而HttpServlet的请求就从doGet/doPost开始 DispatcherServlet本身没有实现doGet/doPost,而由他的父类FrameworkServlet实现,源码如 <a href="https://www.cnblogs.com/lusaisai/p/15983121.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983111.html
03-SpringMVC容器初始化 - 路仁甲
Servlet项目启动执行顺序 由前面的回顾内容可知,Servlet项目启动执行顺序如下 ServletContainerInitializer.onStartup(Set<Class<?>> c, ServletContext ctx) ServletContextListener.context
2022-03-08T15:29:00Z
2022-03-08T15:29:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】Servlet项目启动执行顺序 由前面的回顾内容可知,Servlet项目启动执行顺序如下 ServletContainerInitializer.onStartup(Set<Class<?>> c, ServletContext ctx) ServletContextListener.context <a href="https://www.cnblogs.com/lusaisai/p/15983111.html" target="_blank">阅读全文</a>
https://www.cnblogs.com/lusaisai/p/15983096.html
02-手写简易SpringMVC - 路仁甲
手写简易SpringMVC 思路分析: 1.启动tomcat 2.spi机制加载spring容器,扫描包,生成bean,并且将注解解析到Map<String,RequestMappingInfo> map中 3.get/post请求时,. 根据url获取对应的RequestMappingInfo对象
2022-03-08T15:26:00Z
2022-03-08T15:26:00Z
路仁甲
https://www.cnblogs.com/lusaisai/
【摘要】手写简易SpringMVC 思路分析: 1.启动tomcat 2.spi机制加载spring容器,扫描包,生成bean,并且将注解解析到Map<String,RequestMappingInfo> map中 3.get/post请求时,. 根据url获取对应的RequestMappingInfo对象 <a href="https://www.cnblogs.com/lusaisai/p/15983096.html" target="_blank">阅读全文</a>