多线程与高并发—JUC之AQS、ReentrantLock、读写锁原理等
AQS概述全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架。
特点
用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁:
getState:获取 state 状态。
setState:设置 state 状态。
compareAndSetState:cas 机制设置 state 状态。
独占模式只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源。
提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList。
条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet。
子类主要实现这样一些方法(默认抛出 UnsupportedOperationException):
tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
isHeldExclusively
1234567891011// 获取锁的姿势// 如果获取锁失败if (!tryAcqu ...
多线程与高并发—线程池
线程池线程池介绍池化技术现在已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。
线程池提供了一种限制和管理资源(包括执行一个任务)的方式。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。
使用线程池的好处:
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
自定义线程池
上图就是一个线程池的实现,先初始化线程池、阻塞队列大小,然后开几个线程通过线程池对象调用方法执行任务,如果任务过多,会添加到阻塞队列中,线程执行完任务再从阻塞队列中取值继续执行。当执行的线程数大于线程池和阻塞队列的大小,我们可以定义拒绝策略,类似 jdk 线程池那样。代码实现如下:
123456789101112131415161718192021222324252627282930 ...
多线程与高并发—JMM、Volatile、CAS
共享模型之内存Java 内存模型(JMM)JMM 即 Java Memory Model,它定义了主存(共享内存)、工作内存(线程私有)的抽象概念,底层对应着 CPU 寄存器、缓存、硬件内存、 CPU 指令优化等。
JMM 体现在以下几个方面:
原子性 - 保证指令不会受到线程上下文切换的影响。
可见性 - 保证指令不会受 cpu 缓存的影响。
有序性 - 保证指令不会受 cpu 指令并行优化的影响。
可见性退不出的循环先来看一个现象,main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止:
1234567891011121314151617181920public static boolean run = true; public static void main(String[] args) { Thread t1 = new Thread(() -> { while(run) { } }, "t1" ...
多线程与高并发—共享模型之管程
共享模型之管程线程共享带来的问题线程出现问题的根本原因是因为线程上下文切换,导致线程里的指令没有执行完就切换执行其它线程了。
123456789101112131415161718public static int count = 0; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 1;i < 5000; i++){ count++; } }); Thread t2 = new Thread(() -> { for (int i = 1;i < 5000; i++){ count--; } } ...
SpringBoot自动装配原理
什么是 SpringBoot 自动装配?现在提到自动装配的时候,一般会和 Spring Boot 联系在一起。但是,实际上 Spring Framework 早就实现了这个功能。Spring Boot 只是在其基础上,通过 SPI 的方式,做了进一步优化。
SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。
没有 Spring Boot 的情况下,如果需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。
1234<dependency> < ...
ThreadLocal源码解析
ThreadLocal前言
问题:
ThreadLocal的 key 是弱引用,那么在 ThreadLocal.get()的时候,发生GC之后,key 是否为null?
ThreadLocal中ThreadLocalMap的数据结构?
ThreadLocalMap的Hash 算法?
ThreadLocalMap中Hash 冲突如何解决?
ThreadLocalMap的扩容机制?
ThreadLocalMap中过期 key 的清理机制?探测式清理和启发式清理流程?
ThreadLocalMap.set()方法实现原理?
ThreadLocalMap.get()方法实现原理?
项目中ThreadLocal使用情况?遇到的坑?
……
ThreadLocal代码演示ThreadLocal使用示例:
1234567891011121314151617181920212223public class ThreadLocalTest { private List<String> messages = Lists.newArrayList(); public st ...
Spring Cloud
什么是Spring CloudSpring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
设计目标与优缺点设计目标协调各个微服务,简化分布式系统开发。
优缺点优点:
产出于Spring大家族,Spring在企业级开发框架中无人能敌,来头很大,可以保证后续的更新、完善;
组件丰富,功能齐全。Spring Cloud 为微服务架构提供了非常完整的支持。例如、配置管理、服务发现、断路器、微服务网关等;
Spring Cloud 社区活跃度很高,教程很丰富,遇到问题很容易找到解决方案;
服务拆分粒度更细,耦合度比较低,有利于资源重复利用,有利于提 ...
Dubbo
基础知识RPC是什么?RPC(Remote Procedure Call) 即远程过程调用。
为什么要 RPC ? 因为,两个不同的服务器上的服务提供的方法不在一个内存空间,所以,需要通过网络编程才能传递方法调用所需要的参数,并且,方法调用的结果也需要通过网络编程来接收。但是,如果我们自己手动网络编程来实现这个调用过程的话工作量是非常大的,因为,我们需要考虑底层传输方式(TCP还是UDP)、序列化方式等等方面。
**RPC 能帮助我们做什么呢? ** 简单来说,通过 RPC 可以帮助我们调用远程计算机上某个服务的方法,这个过程就像调用本地方法一样简单。并且!我们不需要了解底层网络编程的具体细节。
一言蔽之:RPC 的出现就是为了让你调用远程方法像调用本地方法一样简单。
RPC 的原理是什么?
客户端(服务消费端) :调用远程方法的一端。
客户端 Stub(桩) : 这其实就是一代理类。代理类主要做的事情很简单,就是把你调用方法、类、方法参数等信息传递到服务端。
网络传输 : 网络传输就是你要把你调用的方法的信息比如说参数啊这些东西传输到服务端,然后服务端执行完之后再把返回结果通过网 ...
动态规划之背包问题
动态规划之背包问题01背包有N件物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
416. 分割等和子集(能否能装满背包)1234567891011121314151617181920class Solution { public boolean canPartition(int[] nums) { int len=nums.length; int sum=0; for(int n:nums){ sum+=n; } if(sum%2!=0) return false; int bagSize=sum/2; int[] dp=new int[bagSize+1]; dp[0]=0; //先遍历物品再遍历背包 for(int i=0;i<len;i++) ...
分布式缓存
分布式缓存在项目中缓存是如何使用的?缓存如果使用不当会造成什么后果?项目中缓存是如何使用的?这个,需要结合自己项目的业务来。
为什么要用缓存?用缓存,主要有两个用途:高性能、高并发。
用了缓存之后会有什么不良后果?常见的缓存问题有以下几个:
缓存与数据库双写不一致
缓存雪崩、缓存穿透
缓存并发竞争
缓存数据的处理流程是怎样的?简单来说就是:
如果用户请求的数据在缓存中就直接返回;
缓存中不存在的话就看数据库中是否存在;
数据库中存在的话就更新缓存中的数据;
数据库中不存在的话就返回空数据。
Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么单线程的 Redis 比多线程的 Memcached 效率要高得多?redis 和 memcached 有啥区别?共同点 :
都是基于内存的数据库,一般都用来当做缓存使用。
都有过期策略。
两者的性能都非常高。
区别 :
Redis 支持更丰富的数据类型(支持更复杂的应用场景)。Redis 不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。Mem ...