能力说明:
精通JVM运行机制,包括类生命、内存模型、垃圾回收及JVM常见参数;能够熟练使用Runnable接口创建线程和使用ExecutorService并发执行任务、识别潜在的死锁线程问题;能够使用Synchronized关键字和atomic包控制线程的执行顺序,使用并行Fork/Join框架;能过开发使用原始版本函数式接口的代码。
暂时未有相关云产品技术能力~
个人公众号:『 程序员小航 』
在开发过程中,打印日志是必不可少的,因为日志关乎于应用的问题排查、应用监控等。现在打印日志一般都是使用 slf4j,因为使用日志门面,有助于打印方式统一,即使后面更换日志框架,也非常方便。在 《Java 开发手册》中也有相关的规约。
Doc View 是一款快捷生成接口文档 IDEA 插件,使用 Doc View 可以将开发人员从繁琐的文档编写中释放出来,极大的节省开发时间。
单元测试,还需要写集成测试,就是模拟全流程的请求。 集成测试同样使用的是 MockMvc,但是如果像单元测试一样加上 @WebMvcTest 就不太可以,因为 Service 代码没有 mock 掉,就会报错。
有时候新创建应用还没有添加 `.gitignore` 文件或者 `.gitignore` 内容设置的不正确,就导致 `.idea` 文件目录上传到了仓库(也可能是其他文件)。 可以使用以下方式删除仓库中的 `.idea` 文件。
下面只是在工作中可能会遇到的一个场景,所以记录下来,如果小伙伴有更合适的方式来统计计算,欢迎留言。
在工作中基本上都会使用定时任务,常用的有 Spring 定时框架、Quartz、elastic-job、xxl-job 等。这里说不上框架的好坏,只有适合自己的才是最好的,本文仅从个人角度上谈一谈对定时任务的看法。
在 JDK 中有很多锁,包括 synchronized、ReentrantLock、ReentrantReadWriteLock、锁的使用场景也分很多种,下面看一下对加锁优化的小技巧。
最近频繁遇到找不到类文件错误。 Caused by: java.lang.NoClassDefFoundError:xxx 就这个家伙。
Curator 同样支持分布式读写锁 和联锁,只需要使用 InterProcessReadWriteLock 即可,来一起看看它的源码以及实现方式。
分布式信号量,之前在 Redisson 中也介绍过,Redisson 的信号量是将计数维护在 Redis 中的,那现在来看一下 Curator 是如何基于 ZooKeeper 实现信号量的。
在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的?
加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢?
一般工作中常用的分布式锁,就是基于 Redis 和 ZooKeeper,前面已经介绍完了 Redisson 锁相关的源码,下面一起看看基于 ZooKeeper 的锁。也就是 Curator 这个框架。
Redisson 除了提供了分布式锁之外,还额外提供了同步组件,Semaphore 和 CountDownLatch。
Redisson 还支持可重入读写锁,允许在分布式场景下,同时有多个读锁和一个写锁处于加锁状态。
RedLock 红锁,是分布式锁中必须要了解的一个概念。 所以本文会先介绍什么是 RedLock,当大家对 RedLock 有一个基本的了解。然后再看 Redisson 中是如何实现 RedLock 的。
基于 Redis 的 Redisson 分布式联锁 RedissonMultiLock 对象可以将多个 RLock 对象关联为一个联锁,每个 RLock 对象实例可以来自于不同的 Redisson 实例。 当然,这是官网的介绍,具体是什么?一起看看联锁 MultiLock 使用以及源码吧!
看门狗机制是在 RedissonBaseLock#scheduleExpirationRenewal 方法中,这块公平锁和非公平锁并无区别。 前文已经了解到,公平锁加锁失败之后,会将当前放到等待队列中,通过 Java 代码中的循环不断尝试获得锁。
在上一篇文章中已经分析过公平锁的加锁源码,并得出结论: 1. Redis Hash 数据结构:存放当前锁,Redis Key 就是锁,Hash 的 field 是加锁线程,Hash 的 value 是 重入次数; 2. Redis List 数据结构:充当线程等待队列,新的等待线程会使用 rpush 命令放在队列右边; 3. Redis sorted set 有序集合数据结构:存放等待线程的顺序,分数 score 用来是等待线程的超时时间戳。 现在看一下加锁失败被放到等待队列之后,线程是如何处理的?
默认的加锁逻辑是非公平的。 在加锁失败时,线程会进入 while 循环,一直尝试获得锁,这时候是多线程进行竞争。就是说谁抢到就是谁的。
前面已经了解到了,可重入锁加锁,看门狗以及锁的互斥阻塞。 当锁加锁成功之后,锁是如何释放的?
看过可重入锁的 Lua 脚本,已经可以知道当锁存在时,是会加锁失败的。 下面看一下,加锁失败之后是如何处理的呢?
说起 Redisson,比较耳熟能详的就是这个看门狗(Watchdog)机制。 本文就一起看看加锁成功之后的看门狗(Watchdog)是如何实现的?
相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize、ReentrantLock 等等等,那分布式系统如何处理?
相信小伙伴一定用过 @Transactional 注解,那 @Transactional 背后的秘密又知道多少呢? Spring 是如何开启事务的?又是如何进行提交事务和关闭事务的呢?
我要写个 IDEA 插件,以后再也不想手写文档了! 下面,来看看我肝出来的插件吧!
三篇文章分别通过实际操作,介绍了主键、非主键唯一索引、普通索引、普通字段四个方面介绍了加锁的范围。 本篇文章再做一个总结。
前面已经介绍了主键索引的加锁范围和非主键唯一索引的加锁范围。 MySQL next-key lock 加锁范围是什么? 看来,MySQL next-key lock 的 bug 并没有被修复!
在上一篇文章《MySQL next-key lock 加锁范围是什么?》中已经介绍了主键索引的加锁范围,现在来回顾一下
作为开发,在本机捣鼓一下 Docker 还是很有必要的,本篇文章介绍如何使用 Docker 安装 MySQL,并在终端(iTerm2)使用命令连接 MySQL。
本文主要通过实际操作,对主键加锁时的 next-key lock 范围进行了验证,并查阅资料,对比版本得出不同的结论。
记录一下自己用的 Mac 软件,如果小伙伴需要,可以下载体验一下。 在 Github 上有一个地址: github.com/jaywcjlove/… 这里仅介绍我所使用过,并一直在使用,而且觉得很不错的软件推荐给小伙伴。
前段时间有小伙伴在群里聊天,说到 Toolkit 下载量到 4.9k 了。就突然想起来,很久没有更新这个插件。
建造者模式是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。 一个 Builder 类会一步一步构造最终对象。这个 Builder 类是独立于其他对象的。
策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。
本文通过自定义模版,在 IDEA 中,通过简单的几个字符,快捷生成既定的代码。
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。 通俗说法,就是将一个类作为原型,然后复制出来另一个类。
“工欲善其事,必先利其器。” 所以说今天来看一看如何压榨 IDEA ,让你的 IDEA 使用的更顺手! 今日技巧: • 后缀完成 • 自定义后缀完成模版
在循环依赖中有一种循环依赖,就是自注入:自己依赖自己。
在研究 『 Spring 是如何解决循环依赖的 』 的时候,了解到 Spring 是借助三级缓存来解决循环依赖的。
在我的一篇文章中介绍如何避免 Spring 自调用事务失效,其中网友给建议,说可以在类中注入自身,然后调用,而注入自身的过程也是循环依赖的处理过程。 下面就一起看一看,什么是循环依赖,以及 Spring 是如何解决循环依赖的?
在 finishBeanFactoryInitialization 中介绍了创建 Bean 的流程大概流程,这里进入单例 Bean 的创建过程。
可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。 具体怎么操作的,那就一起阅读源码吧! 不过在阅读源码之前,还是需要了解一些知识的。 1. 什么是 FactoryBean ? 2. FactoryBean 是如何使用的 ? 3. Bean 是如何初始化的? 4. 常说的循环依赖是怎么解决的?
上一篇介绍了国际化的使用以及初始化消息源的源码,接下来接着往下阅读,将进入 initApplicationEventMulticaster 、onRefresh 和 registerListeners 的相关操作逻辑。 这一部分主要是初始化事件广播器以及注册监听器。而 onRefresh 部分则需要子类去实现。 所以本文主要介绍以下几个部分: 1. 什么是 Spring 事件? 2. 监听器是如何使用的?
在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。 依然如之前所示,先通过官网了解到国际化的用法,然后再对源码进行研究。
前面通过 invokeBeanFactoryPostProcessors 这一步了解到了什么是 BeanFactoryPostProcessor ,以及 BeanFactoryPostProcessor 的使用及作用,并通过 invokeBeanFactoryPostProcessors 这一步源码,对 BeanFactoryPostProcessor 的加载流程有了进一步了解。
通过以上的阅读,对 invokeBeanFactoryPostProcessors(beanFactory); 这一步方法进行总结。
根据 refresh 流程,当 obtainFreshBeanFactory 执行结束后,下一步会执行 prepareBeanFactory ,顾名思义,这个方法主要是准备 BeanFactory,下面一起看一看这部分逻辑。
前面的准备工作结束之后,就是进入核心代码 refresh。
近期工作开始忙起来,各种忙,连阅读 Spring 源码都暂停了,Doc View 也暂时搁置计划,虽然想有很多功能,但是总是要慢慢来的。