ThreadLocal用法

ThreadLocal 用法

ThreadLocal从字面意思来说,独立线程空间的意思,所以其用法也很简单,就是当一个线程需要有自己的变量,并且这个变量不想和其他变量共享,那么就使用ThreadLocal 变量:

比如常见的我们经常使用SimpleDateFormate 这个类对 date 类型的变量做格式化操作,但是众所周知,这个类是非线程安全的,所以如果像下面这样,把这个解析操作放在util类里面,这样就会有线程安全问题:

public class DateUtils {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");

    public Date convertDate() throws ParseException {
        return sdf.parse("2023-11-05");
    }
} 

当 DateUitls 是单例的情况下,就会有线程安全问题,因为parse方法是非线程安全的

这里的单例就是说当这个类被spring 管理,或者说是spring的一个bean的时候,那么这个bean其实是属于主线程的,所以在主线程里创建了很多其他线程,然后在使用这个bean util的时候,会从主线程里拿到这个bean到自己的线程空间执行,一旦线程很多,那么这个就有线程安全问题

所以改成用threadLocal就可以了:

ThreadLocal t = ThreadLocal.withInitial(()->{return new SimpleDateFormat("yyyy-mm-dd");});

    public Date convertDate() throws ParseException {
        return t.get().parse("2023-11-05")
    }

这样,每个线程独立的拥有对象 t,虽然方法是公用的,但是里面的 t 对象是线程独有的,所有就解决了冲突问题

ThreadLocal 的使用场景

有些伙伴会问了,我使用同步的方式也能解决上述问题呀,把 SimpleDateFormate 对象做同步一下就可以了

是的,使用同步可以解决问题,但是我们要看哪一种方式更合适,一般必须使用同步的场景是这个变量属于业务共享的,也就是说一个线程操作这个对象对别的线程是有业务影响的,是有业务逻辑关系的,再或者说其他线程操作这个变量要看当前线程操作的结果,比如商品库存,这个你总不能说用 ThreadLocal 去定义这个库存吧,那岂不是要疯了。。。总之,,,怎么都能理解吧,这种情况下,必须要使用同步,不能使用 ThreadLocal

而另一种情况就是刚刚那个 SimpleDateFormate 的使用场景,每个线程间操作这个对象对其他线程是否使用或者操作这个对象没有毛线影响,那可以使用 ThreadLocal 对象,还有一些场景比如 User 信息这种。。。

欢迎讨论~~

你可能感兴趣的:(Java,多线程,java,jvm,开发语言)