在 Java 中,如果要问哪个类使用简单,但用好最不简单?我想你的脑海中一定会浮现出一次词——“ThreadLocal”。
确实如此,ThreadLocal
原本设计是为了解决并发时,线程共享变量的问题,但由于过度设计,如弱引用和哈希碰撞,从而导致它的理解难度大和使用成本高等问题。当然,如果稍有不慎还是导致脏数据、内存溢出、共享变量更新等问题,但即便如此,ThreadLocal 依旧有适合自己的使用场景,以及无可取代的价值,比如本文要介绍了这两种使用场景,除了 ThreadLocal
之外,还真没有合适的替代方案。
使用场景1:本地变量
我们以多线程格式化时间为例,来演示 ThreadLocal
的价值和作用,当我们在多个线程中格式化时间时,通常会这样操作。
① 2个线程格式化
当有 2 个线程进行时间格式化时,我们可以这样写:
import java.text.SimpleDateFormat; import java.util.Date; publicclass Test { public static void main(String[] args) throws InterruptedException { // 创建并启动线程1 Thread t1 = new Thread(new Runnable() { @Override public void run() { // 得到时间对象 Date date = new Date(1 * 1000); // 执行时间格式化 formatAndPrint(date); } }); t1.start(); // 创建并启动线程2 Thread t2 = new Thread(new Runnable() { @Override public void run() { // 得到时间对象 Date date = new Date(2 * 1000); // 执行时间格式化 formatAndPrint(date); } }); t2.start(); } /** * 格式化并打印结果 * @param date 时间对象 */ private static void formatAndPrint(Date date) { // 格式化时间对象 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss"); // 执行格式化 String result = simpleDateFormat.format(date); // 打印最终结果 System.out.println("时间:" + result); } }
以上程序的执行结果为:
上面的代码因为创建的线程数量并不多,所以我们可以给每个线程创建一个私有对象 SimpleDateFormat
来进行时间格式化。