- 博客(37)
- 收藏
- 关注
原创 SpringBoot项目中引入Redis
上一篇我们搭建了一个SpringBoot项目,这一节将介绍如何引入redis。2.添加连接配置3.测试连接编写一个简单的测试接口用postman测试上面步骤我们采用了RedisTemplate类来操作Redis,该类操作其它类型Redis数据的方法如下为了更简便操作Redis,我们一般重新封装RedisTemplate类。5.测试编写测试接口postman测试...
2022-07-06 20:00:00
4906
1
原创 用SpringBoot快速搭建一个后端项目
如果我们需要开发一个简单的后端服务,只包含对mysql的简单操作,那么该如何搭建呢?首先,新建一个maven项目,点击next。输入项目名,点击Finish。3. 编写配置文件配置文件主要包含了数据库的连接信息4.逆向工程生成代码创建一个表,下面以该表为例逆向工程的代码如下修改数据库连接配置,然后运行main方法。在控制台输入表名,最后回车,即可看到逆向工程生成的文件。6.编写统一返回类6.测试到这里,我们已经搭建起了一套脚手架。下面我们来写个测试接口。启动项目后,用post
2022-07-04 15:25:19
2680
原创 微信公众号如何接入Java后台
编写代码之前我们需要引入两个依赖。我们需要向微信后台暴露一个接口,以供微信调用。这里采用请求方式,请求路径自己定义。微信会给我们传、、和四个参数,我们需要做的是用前三个参数做校验,校验成功之后原封不动的返回。这里需要自定义设置一个TOKEN的值,后续配置用得到。2.公众号配置登陆公众号后台,选择基本配置。URL填入你的接口地址,Token与步骤1中定义的TOKEN保持一致。简单起见,EncodingAESKey随机生成,消息加密方式选择明文模式。点击提交,提示提交成功。3.接收用户消息上
2022-06-29 16:55:53
2052
1
原创 利用VirtualBox搭建多台centos机器,并且用xshell连接
搭建一个集群需要用到多台机器的时候,购买服务器显然不现实。今天介绍一个利用VirtualBox搭建集群的方法。1.安装VirtualBox可以在官网下载合适版本https://www.virtualbox.org/wiki/Downloads这里给出一个6.1.32版本的百度云资源链接:https://pan.baidu.com/s/1uw6Jq7YecnoSRRq9H1LCyw提取码:zg1l下载完毕之后点击安装安装全部下一步就好了,安装地址建议改成d盘。2. 安装centos72..
2022-05-20 21:17:17
962
原创 线程池执行任务发生异常
先说结论1.调用线程池的excutor()方法执行任务,如果有异常,线程终止,等待垃圾回收,并在下一次执行任务时,创建新的线程。2.调用submit()方法执行任务,如果有异常,作为结果返回,在结果Future调用get()方法时抛出,线程仍可复用。验证excutor()public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService poolEx
2022-03-04 11:44:28
1428
原创 ThreadLocal会不会造成内存泄露
ThreadLocal的引用在jvm中如下图:因为CurrentThreadRef -> CurrentThread -> Map -> Entry该引用链是强引用,所以Entry的生命周期与线程一致。所以只要线程存活,GC就不可能把Entry回收,造成内存泄露。如何避免内存泄露由图中的引用链可知,只要线程还存活,就一定会有内存泄露的问题。因此避免泄露的方法一:使用完ThreadLocal,当前Thread也随之运行结束。还有一种更直接的方法二:使用完ThreadLocal,
2022-02-19 18:03:06
369
原创 ThreadLocal内存模型
jdk8开始,ThreadLocal内存模型发生了改变。原先的内存模型,每个ThreadLocal都创建ThreadLocalMap,ThreadLocalMap中线程作为key,从而达到线程隔离的效果。jdk8开始,每个线程都维护了一个ThreadLocalMap,ThreadLocalMap中ThreadLocal作为key更详细的示意图如下:两者的差别就在于,ThreadLocal和Thrad位置互换。这样带来的好处有:ThreadLocal数量比Thread少,ThreadLoca
2022-02-19 17:33:17
520
转载 Bitmap的原理与用法
Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。(PS:划重点 节省存储空间)假设有这样一个需求:在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存在Java中,int占4字节,1字节=8位(1 byte = 8 bit)如果每个数字用int存储,那就是20亿个int,因而占用的空间约为 (2000000000*4/1024/1024/1024)≈7.45G如
2022-02-17 15:46:47
1068
原创 Redis的AOF和RDB会不会造成阻塞
目前,Redis的持久化主要有两大机制,即AOF日志和RDB快照。那么通过这两种方式进行持久化的时候,会不会阻塞redis的读写,造成redis的性能下降呢?AOFAOF是写后日志,它是先执行命令,把数据写入内存,然后才记录日志。AOF日志是在主线程中执行的,采用先存数据再写日志的方式,可以避免对当前命令的阻塞。但可能会给下一个操作带来阻塞风险。这是因为如果把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而阻塞后续操作。AOF提供了三种写回策略,也就是AOF配置项appendfsync的三
2022-01-20 16:31:30
2941
原创 springcloud 使用nacos做配置中心
1. 引入依赖首先引入配置中心的启动类依赖,以下两个依赖分别是spring和阿里的启动类配置依赖,二者选其一即可。<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>0.2.0.RELEASE&l
2022-01-15 23:30:09
4443
3
原创 单例模式懒汉式加volatile优化
单例模式只要记住构造方法私有化,就能将代码写出。public class LazySingleton { private static People people = null; private LazySingleton() {}; public static People getSingleton() { synchronized (LazySingleton.class) { if (people == null) {
2022-01-02 18:57:01
550
原创 一文看懂二分查找
二分查找原理二分查找的原理不难理解,即在一个有序数组中,每次将数组中间值与目标值进行比较,从而判断目标值在中间值的左边还是右边。由于每次可排除一半的数,因此二分查找的时间复杂度为log2n。对于100万个有序数据,利用二分查找仅需搜索20次,效率非常高。mysql的B+树叶子节点的数据查找,用的就是二分查找。代码编写中间值第一次写二分查找的代码时,都会有一个疑惑,那就是如果数组的个数是奇数和偶数时,中间值要不要分别处理?再加上数组的起始值是从0开始,相信当你仔细去区分时,十有八九会被绕晕。我们完全
2022-01-01 12:05:13
869
原创 保护性暂停模式
定义保护性暂停模式(Guarded Suspension Design Pattern):当线程在访问某个对象时,发现条件不满足时,就暂时挂起等待条件满足时再次访问。要点:有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)JDK 中,join 的实现、Future 的实现,采用的就是此模式代码实现public class GuardedObject<V> {
2021-12-25 17:47:01
216
原创 Redis的内存淘汰策略
Redis中共有下面八种内存淘汰策略:volatile-lru:设置了过期时间的key使用LRU算法淘汰;allkeys-lru:所有key使用LRU算法淘汰;volatile-lfu:设置了过期时间的key使用LFU算法淘汰;allkeys-lfu:所有key使用LFU算法淘汰;volatile-random:设置了过期时间的key使用随机淘汰;allkeys-random:所有key使用随机淘汰;volatile-ttl:设置了过期时间的key根据过期时间淘汰,越早过期越早淘汰;noe
2021-12-17 10:50:19
798
原创 Redison看门狗机制
Redison提供了看门狗机制实现Redis分布式锁的自动续期。//1、获取一把锁,只要锁的名字一样,就是同一把锁RLock lock = redisson.getLock("my-lock");//2、加锁lock.lock(30,TimeUnit.SECONDS); // 省掉了整个续期操作。手动解锁lock.lock(); //默认加的锁都是30s时间。看门狗机制自动续期。如上,Redison加分布式锁的两个重载方法。方法一:lock.lock(30,TimeUnit.SECOND
2021-12-15 16:26:41
2634
原创 synchronized锁膨胀过程
如果在尝试加轻量级锁的过程中,CAS操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。当 Thread-1 进行轻量级加锁时,Thread-0 已经对该对象加了轻量级锁这时 Thread-1 加轻量级锁失败,进入锁膨胀流程即为 Object 对象申请 Monitor 锁,让 Object 指向重量级锁地址然后自己进入 Monitor 的 EntryList BLOCKED当 Thread-0 退出同步块解锁时,使用 c
2021-12-14 14:28:31
400
原创 synchronized的偏向锁、轻量级锁和重量级锁
Java对象头普通对象数组对象其中 Mark Word在64 位虚拟机中的结构为Mark Word后三位001:无锁状态101: 偏向锁00: 轻量级锁10:重量级锁偏向锁Jdk6开始,默认开启偏向锁。当第一次获取锁资源时,自动加上偏向锁。Mark Word中的thread保存偏向的线程id。当锁释放之后,另一线程获得锁资源,则偏向锁升级为轻量级锁。若锁还未释放,另一线程就来竞争锁资源,则偏向锁直接升级为重量级锁。调用hashcode方法,因为没有空间存储hashcod
2021-12-14 14:17:28
2506
3
原创 Redis分布式锁浅析
redis有一个命令: set key value nx;该命令的用处是,只有当redis中不含key时,才能set成功。基于以上原理,可以设计分布式锁。分布式锁可用于防止redis缓存击穿的问题,也可解决幂等性问题。分布式锁设计思路:分布式锁会设置一个过期时间,以防止服务器在解锁前突然宕机,导致死锁。因此加锁和设计过期时间得设计成原子性操作。分布式锁解锁的过程,也存在问题。若业务超时,锁已过期,而业务完成之后默认会删除锁,而此时的锁已经是别人的锁了,导致误删。为了解决这一问题,可将key设置为
2021-12-01 15:22:05
988
原创 Redis的AOF日志为什么先执行命令再写日志?
我们比较熟悉的是数据库的写前日志(Writer Ahead Log, WAL),也就是说,在实际写数据前,先把修改的数据记到日志文件中,以便故障时恢复。不过,AOF日志正好相反,它是写后日志,“写后”的意思是Redis是先执行命令,然后才记录日志,如下图所示:AOF为什么要先执行命令再记日志呢?为了避免额外的开销,Redis在向AOF里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,若命令有错,并在记日志之后发生宕机,日志中就有可能记录了错误的命令,Redis在使
2021-11-01 16:25:07
1309
6
原创 mysql查询语句的执行过程
一句简单的sql查询代码,mysql是怎么执行的呢?mysql> select * from T where ID=10;执行步骤如图所示:1. 连接器第一步,你会先连接到这个数据库上,这时候接待你的就是连接器。连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接命令一般是这么写的:mysql -h$ip -P$port -u$user -p2. 查询缓存MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以key-val
2021-11-01 10:48:31
145
原创 Java线程的两阶段终止
终止java线程若采用stop方法,容易使共享资源来不及释放,造成死锁。采用两阶段终止,可防止该情况的发生。@Slf4jclass TwoPhaseTermination { private Thread monitor; public void start() { monitor = new Thread(() -> { while (true) { Thread cur = Thread.curren
2021-10-20 16:33:24
117
原创 Java虚拟机类加载过程
类加载的完整过程:加载 --> 链接(验证 -> 准备 -> 解析)–> 初始化加载(Loading)阶段1、通过一个类的全限定名获取定义此类的二进制字节流2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构3、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口加载.class文件的方式:从本地系统中直接加载通过网络获取,典型场景:Web Applet从zip压缩包中读取,成为日后jar、war格式的基
2021-10-15 15:50:03
193
原创 自定义注解生成操作日志
1. 创建自定义注解@Documented@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface OperationDetail { /** * 方法描述 */ String detail() default ""; /** * 日志操作级别 */ int level() default 0; /**
2021-10-08 17:22:13
261
原创 构建二叉树类题目总结
常见的构建二叉树的题目有:1.利用先序(或后序)和中序遍历构建二叉树2.利用有序联表或数组构建平衡二叉树解决这类问题通常采用递归方式,而递归方法要做的事,就是找到根节点。类型1的题目,根节点为先序遍历的第一位(后序遍历的最后一位),找到根节点之后,我们利用递归找左子树的根。中序遍历具有一个特点,那就是根节点的左边都是它的左子树节点,右边都是它右子树节点。再计算左右子树节点个数,得到左右子树的先序遍历顺序。代码如下public TreeNode buildTree(int[] preorder, i
2021-09-29 17:13:08
199
原创 快排的两种实现方式(Two way quicksort 和 Three way quicksort)
三分快排与二分快排的平均时间复杂度都为O(nlogn),区别在于:二分快排(Two way quicksort),即将数组分为两部分,一部分小于等于枢纽元,一部分大于等于枢纽元。三分快排(Three way quicksort),将数组分为三部分,一部分小于枢纽元,一部分等于枢纽元,一部分大于枢纽元。将该数组{4, 5, 4, 1, 4, 5, 3, 4, 6}分别进行二分和三分快排,debug记录第一遍排序结果如下。二分快排:三分快排:二分快排代码如下:public void quick
2021-09-27 22:28:11
438
原创 快速选择法找数组第K大的元素
快速选择法是快速排序的改版。可以用该方法寻找第k大的元素,若k为数组长度的一半,则以为着找到的数为中位数。我们知道快速排序的平均时间复杂度为O(nlogn),而快速选择法的平均时间复杂度为O(n) (证明过程见快速选择的平均时间复杂度)。快速选择法的思想是:选取枢纽元,遍历数组,使数组左边的值都大于等于枢纽元,右边的值都小于等于枢纽元。若此时枢纽元的下标为 k - 1,则找到第k大的元素。若此时枢纽元的下标大于 k - 1, 则从左半段进行递归查找。若此时枢纽元的下标小于k + 1, 则从右半段
2021-09-27 21:16:06
549
原创 二分搜索、快排、堆排序、归并排序
二分搜索对于一个有序数组,采用二分搜索的方式,可将时间复杂度由O(n) 降为 O(logn)。二分搜索的思想即,每次取数组中间位置的值与目标进行比较,根据比较结果可排除当前搜索范围的一半。二分搜索的难点在于边界的判断,规定搜索区间即可解决这一问题,常选择的区间为左闭右开。package leetcode.editor.cn;//给定一个排序的整数数组 nums 和一个整数目标值 target ,请在数组中找到 target ,并返回其下标。如果目标值不存在于数组中,返回它将会被按顺//序插入的位
2021-09-18 17:58:33
184
原创 链表的反转、取中、合并
链表的反转public ListNode reverseNode(ListNode head){ if (head == null){ return null; } ListNode pre = null; ListNode p = head; ListNode q = head.next; while (q != null){ p.next = pre; pre = p; p = q; q = q.
2021-08-24 15:38:19
64
原创 两台linux机器之间配置免密
1.在服务器A 运行命令ssh-keygen -t rsa生成公钥和私钥2.将公钥复制到服务器B,并运行命令cat id_rsa.pub >> authorized_keys将公钥的内容写入authorized_keys。3.这个时候在服务器A通过命令ssh root@服务器BIp 免密登录服务器B了。...
2021-08-02 21:47:15
441
原创 MYSQL为什么我改了之后我看不到?
先上图可以看到,同一个事务中,先查询了一遍,然后执行update t set c=0 where id=c;按理来说,这时4行数据的c值都为0才对。为什么再次查询,结果仍和第一次一样呢?给出答案:我们知道,mysql的默认事务隔离级别是可重复读。当事务A开启了事务之后,会开启一个视图,在A这个视图中,select语句读的是这个视图内的记录,更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。所以执行update语句时,c的值已被事务B给改变了,所以这里
2021-07-14 11:16:00
420
原创 spring的七种事务传播级别
总结:[1]死活不要事务的PROPAGATION_NEVER:没有就非事务执行,有就抛出异常PROPAGATION_NOT_SUPPORTED:没有就非事务执行,有就直接挂起,然后非事务执行[2]可有可无的PROPAGATION_SUPPORTS: 有就用,没有就算了[3]必须有事务的PROPAGATION_REQUIRES_NEW:有没有都新建事务,如果原来有,就将原来的挂起。PROPAGATION_NESTED: 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。PROPA
2021-07-12 20:31:52
324
原创 事务的隔离级别及springboot使用事务
事务会产生的问题:脏读、不可重复读、幻读。事务的隔离级别有:读未提交、读已提交、重复读、序列化。读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。读已提交是指,一个事务提交之后,它做的变更才会被其他事务看到。可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完
2021-07-12 18:35:04
817
原创 JDK与Cglib动态代理实现
1.JDK动态代理public class JDKDynamicProxy { public static void main(String[] args) { CAProxy caProxy = new CAProxy(); IA instance = (IA) caProxy.getInstance(new CA()); instance.say(); instance.fly(); }}interface IA
2021-07-10 11:34:03
176
原创 Spring基于注解使用Aop
首先创建一个切面,写好切点和通知,这里我们使用前置通知测试。@Component@Aspectpublic class NotVeryUserfulAspect { @Pointcut("within(com.xufuxin.spring.entity.A)") public void pointCut(){} @Before("pointCut()") public void doBefore(){ System.out.println("这是前置
2021-07-09 15:50:42
67
原创 @PostConstruct、init-method和afterPropertiesSet三种初始化bean的执行顺序
三种方式可以实现bean的生命周期初始化回调1.在方法上加@PostConstruct注解2.在xml中配置init-method方法3.实现InitializingBean接口,并重写afterPropertiesSet方法那么这三种方式同时存在时,它们的执行顺序如何呢?@Component@Datapublic class A implements InitializingBean{ @Autowired private B b; public A(){
2021-07-07 16:45:09
1414
原创 Bean的生命周期小结(一)
Spring实现生命周期初始化回调方法的三种方式1.在xml中配置init-method方法2.在方法上加@PostConstruct注解3.实现InitializingBean接口,并重写afterPropertiesSet方法新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章
2021-07-07 16:30:19
73
原创 jenkins设置清华镜像时报错 unable to find valid certification path to requested target
jenkins在设置清华镜像时,会报找不到证书的错,具体报错内容:检查更新中心: SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 时
2021-04-02 12:52:42
889
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人