阿里出品Excel工具EasyExcel使用小结

前提

笔者做小数据和零号提数工具人已经有一段时间,服务的对象是运营和商务的大佬,一般要求导出的数据是Excel文件,考虑到初创团队机器资源十分有限的前提下,选用了阿里出品的Excel工具EasyExcel。这里简单分享一下EasyExcel的使用心得。EasyExcel从其依赖树来看是对apache-poi的封装,笔者从开始接触Excel处理就选用了EasyExcel,避免了广泛流传的apache-poi导致的内存泄漏问题。

Java

硬核干货:3W字从源码上分析JUC并发组件CountDownLatch的实现原理

前提

之前已经花了大量时间分析同步器框架AQS的源码实现,这篇文章分析一下CountDownLatch的源码实现,本文参看的JDK源码为JDK11,其他版本不一定适合。

CountDownLatch其实是复合名词,由单词countdown和latch复合而来。countdown是倒数的意思,而latch则是闩锁、闭锁的意思,复合词容易让人联想到预先设定一个计数值,并且"锁住(阻塞)“一些东西(线程),然后进行倒数,当数值减少到0的时候进行"放行(解除阻塞)”。

CountDownLatchAQS共享模式下的典型实现。本文会先简单介绍CountDownLatch的基本API、类比监视器方式的实现以及深入分析其源码实现。

硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

前提

很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章。之前在分析扩展线程池实现可回调的Future时候曾经提到并发大师Doug Lea在设计线程池ThreadPoolExecutor的提交任务的顶层接口Executor只有一个无状态的执行方法:

public interface Executor {

    void execute(Runnable command);
}    

ExecutorService提供了很多扩展方法底层基本上是基于Executor#execute()方法进行扩展。本文着重分析ThreadPoolExecutor#execute()的实现,笔者会从实现原理、源码实现等角度结合简化例子进行详细的分析。ThreadPoolExecutor的源码从JDK8JDK11基本没有变化,本文编写的时候使用的是JDK11

硬核干货:5W字17张高清图理解同步器框架AbstractQueuedSynchronizer

前提

并发编程大师Doug Lea在编写JUCjava.util.concurrent)包的时候引入了java.util.concurrent.locks.AbstractQueuedSynchronizer,其实是Abstract Queued Synchronizer,也就是"基于队列实现的抽象同步器",一般我们称之为AQS。其实Doug Lea大神编写AQS是有严谨的理论基础的,他的个人博客上有一篇论文《The java.util.concurrent Synchronizer Framewor》,可以在互联网找到相应的译文《JUC同步器框架》,如果想要深入研究AQS必须要理解一下该论文的内容,然后结合论文内容详细分析一下AQS的源码实现。本文在阅读AQS源码的时候选用的JDK版本是JDK11

出于写作习惯,下文会把AbstractQueuedSynchronizer称为AQS、JUC同步器框或者同步器框架。

MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘

背景

最近有一个数据统计服务需要升级SpringBoot的版本,由1.5.x.RELEASE直接升级到2.3.0.RELEASE,考虑到没有用到SpringBoot的内建SPI,升级过程算是顺利。但是出于代码洁癖和版本洁癖,看到项目中依赖的MyBatis的版本是3.4.5,相比当时的最新版本3.5.5大有落后,于是顺便把它升级到3.5.5。升级完毕之后,执行所有现存的集成测试,发现有部分OffsetDateTime类型入参的查询方法出现异常,于是进行源码层面的DEBUG找到最终的问题并且解决。

Java线程生命周期与状态切换

前提

最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期、状态切换以及线程的上下文切换等等。编写本文的时候,使用的JDK版本是11。

深入理解Java的动态编译

前提

笔者很久之前就有个想法:参考现有的主流ORM框架的设计,造一个ORM轮子,在基本不改变使用体验的前提下把框架依赖的大量的反射设计去掉,这些反射API构筑的组件使用动态编译加载的实例去替代,从而可以得到接近于直接使用原生JDBC的性能。于是带着这样的想法,深入学习Java的动态编译。编写本文的时候使用的是JDK11

Java

通过transmittable-thread-local源码理解线程池线程本地变量传递的原理

前提

最近一两个月花了很大的功夫做UCloud服务和中间件迁移到阿里云的工作,没什么空闲时间撸文。想起很早之前写过ThreadLocal的源码分析相关文章,里面提到了ThreadLocal存在一个不能向预先创建的线程中进行变量传递的局限性,刚好有一位HSBC的技术大牛前同事提到了团队引入了transmittable-thread-local解决了此问题。借着这个契机,顺便clonetransmittable-thread-local源码进行分析,这篇文章会把ThreadLocalInheritableThreadLocal的局限性分析完毕,并且从一些基本原理以及设计模式的运用分析transmittable-thread-local(下文简称为TTL)整套框架的实现。

如果对线程池和ThreadLocal不熟悉的话,可以先参看一下前置文章:

这篇文章前后花了两周时间编写,行文比价干硬,文字比较多(接近5W字),希望带着耐心阅读。

JDK中注解的底层实现

前提

Java快三年了,注解算是一个常用的类型,特别是在一些框架里面会大量使用注解做组件标识、配置或者策略。但是一直没有深入去探究JDK中的注解到底是什么,底层是怎么实现了?于是参考了一些资料,做了一次稍微详细的分析。

Levenshtein Distance(编辑距离)算法与使用场景

前提

已经很久没深入研究过算法相关的东西,毕竟日常少用,就算死记硬背也是没有实施场景导致容易淡忘。最近在做一个脱敏数据和明文数据匹配的需求的时候,用到了一个算法叫Levenshtein Distance Algorithm,本文对此算法原理做简单的分析,并且用此算法解决几个常见的场景。