Java 技术

Java 协程

刘启春

协程本质上和线程是一类概念,本质上是编程过程中对并发计算任务的一种抽象,只不过协程在调度层面上更轻量。

线程的调度由于是操作系统实施的,有时间片/中断等较为复杂的机制,因此调度点对用户是透明的,可以认为调度理论上可以在任何地方触发。而协程的调度点往往是用户代码显式通过触发的(发生在用户态),需要用户代码自己相互“协作”来完成任务的调度和执行,这也是协程中”协“的来源。

Java 进度条工具

刘启春

有时候批量处理任务无法观察执行情况,例如处理进度、处理数量、耗时等,这种“不确定性”会隐藏 bug,等到出问题就晚了。今天,这篇文章的“主角” —— 进度条工具 —— 就是为了解决这个问题。

进度条工具输出预览:

[4B645A43] 远程请求记录: [####                ] - 22.91% (9835/42920), 耗时: 2m32s
   (1)        (2)               (3)               (4)       (5)          (6)

各部分说明:

(1) Trace ID
(2) 进度条名称
(3) 进度条面板
(4) 执行占比
(5) 执行数量细节
(6) 执行耗时

Java 中使用枚举的正确姿势

刘启春

在项目开发中我们经常用到枚举定义常量,例如定义系统中用户的身份类型(ADMIN、USER…)、定义项目启动环境的类型(DEV,PROD…)、某个字段的值的枚举等。往往我们发现在项目里定义枚举类时只是有枚举成员,像下面这样:

public enum Type {
  T1,T2,T3
}

不能说这样不好,只是这样差不多又回到了我们使用类定义静态常量常量。Java 中除了有类(class)这种类型,又实现了枚举(enum)这种类型,说明肯定它独特的用处,不妨我们先回忆下使用类成员定义静态常量和枚举定义常量的区别。

  • 使用类的静态成员定义常量,常量只能有一个固定的值,通常是一个简单的字符串或一个数值。
  • 使用枚举定义常量,实例化枚举后不可变,枚举可以携带多个值,这为常量提供了更多信息。(补充,虽说枚举实例化后不可变,但它的成员变量如果不用 final 修饰,是可变的!)
  • 如果你熟悉枚举的原理,你可以通过类(class)模拟出一个枚举(enum),但通常你需要两个类来完成这个工作,一个类来定义枚举和其成员,另一类完成初始化。而枚举(enum)通过编译消除了这些复杂性,可以轻松实例化对象和定义方法。

通过它们之间的区别,可以看出枚举能为我们的常量提供更多的信息和更加便捷的定义、实例化。那么如何利用好枚举这些特性,如何定义好用(便捷)的枚举呢?

Java|使用 Optional 更好地处理 null 返回值

刘启春

Optional 是一个容器类,是 JDK 8 提供的一个防止引起空指针异常的工具类,可以更好地封装处理返回值。

为什么更推荐使用 Optional 类封装可能为 null 的返回值?在项目开发过程中,没人绝对清楚调用方法的返回值一定存在,开发者也只是尽力保证返回值不为 null,比如查询用户列表没用户时我们就返回长度为 0 的 ArrayList,有种对任何值都不信任的编程方式,但这种方式会形成许多冗余代码,让开发者也很累,不这样做会带来讨厌的 Null Pointer Exception(NPE)问题;其次是在多层次取成员变量时,程序员能判断到吐。Optional 的出现很好的改观了这个问题,一两行代码就能代替繁琐的判空。

本文对 Optional 工具的使用技巧进行总结。

Java|ThreadLocal

刘启春

ThreadLocal 是线程本地变量,用与在线程上下文中共享变量。

ThreadLocal 经常用在框架中,例如 SpringSecurity 用它存储当前请求的操作用户。

  • ThreadLocal 既线程本地变量,可以使变量为线程私有,避免状态共享出现线程安全问题。
  • InheritableThreadLocal 继承 ThreadLocal 实现,可以使子线程共享父线程的 ThreadLocal。
  • FastThreadLocal 是 Netty 实现的一个 ThreadLocal,当从 FastThreadLocalThread 访问时,可以产生更高的访问性能,在 FastThreadLocal 内部使用数组中的索引来查找变量,而不是使用哈希码和哈希表。