final变量

fina指read-only的意思,很容易理解

简单入门

class Student {
    final String name

    Student(String name) {
        this.name = name
    }
}

Student student = new Student("smith")
// 报错
student.name = "changed"

为什么String是final的

String通过final class 与 final array表示String即无法继承,也无法修改,让String在语义上保证不可变性

ThreadLocal

ThreadLocal是线程本地独有可见的变量(各管各的),一般用于上下文管理

简单入门

举个常见的反序列化例子

private static ThreadLocal<SimpleDateFormat> f = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd");
    }
};

原理

threadLocal看起来像是在“栈”上,实际上它还是Thread的成员变量,还是在堆上的,每次实际上通过访问如下获得

//类型如下
//Thread
//ThreadLocal.ThreadLocalMap
//ThreadLocal.ThreadLocalMap.Entry[]
//T
Thread.currentThread().threadLocals.table[i].value

其中

  • i: 通过ThreadLocal的全局成员变量nextHashCode进行自增,每多一个ThreadLocal实例,自增一次
  • value: 通过initialValue传入的对象

在企业开发中的作用

ThreadLocal是线程本地独有可见的变量,一般用于上下文管理

比如

  • 管理Spring-transaction: 数据库事务
  • 管理BPM流程上下文: 这个主要是在企业级应用中使用,自己跳自己的伞,一个线程走到底
  • 业务路由: Tomcat中的getRequestDispatcher进行重定向,比如资源静态化的Filter

在序列化的作用

在进行序列化与反序列化时,内部一定会通过一个状态机来维护上下文,如果它不是线程安全的,那么状态机一定会出问题

  • SimpleDataFormat.parse(不是线程安全)
  • BigDecimal.toString(线程安全)
  • String.<init>(线程安全)