美文网首页
ThreadLocal的使用

ThreadLocal的使用

作者: 文景大大 | 来源:发表于2020-04-29 20:01 被阅读0次

一、为什么要使用

我们在先前的文章《synchronized关键字使用详解》中曾经介绍过,什么场景下不需要考虑线程安全的问题,其中一种场景就是“变量为线程独享变量的时候”,当时的例子如下:

@Slf4j
public class MyThread implements Runnable {
    // 线程独享的变量
    private int count = 200;

    @Override
    public void run() {
        count--;
        log.info("当前线程名称:{},计数器为:{}", Thread.currentThread().getName(), count);
    }
}

在这个例子中,我们的变量是在线程类中的,它并没有使用额外的特殊的修饰符,每启动一个线程,则每个线程都会有一个自己的变量实例,所以不涉及线程安全的问题。

但是,如果这个变量是在线程需要使用的外部类中:

@Slf4j
public class Thread2 implements Runnable {
    @Override
    public void run() {
        while (Counter.counter > 0) {
            Counter.minus();
            log.info("{}当前a值为:{}", Thread.currentThread().getName(), Counter.counter);
        }
    }
}
public class Counter {
    public static int counter = 10;

    public static void minus(){
        count--;
    }
}

此时就会出现线程安全问题了,针对这种情况,我们如何使得每个线程单独保留一份自己的变量实例呢?

主角ThreadLocal就该出现了。

二、入门实例

public class Counter {
    public static ThreadLocal<Integer> counter = new ThreadLocal<>();

    public static void initCounter(){
        counter.set(10);
    }
    public static void minus(){
        Integer cnt = counter.get();
        counter.set(--cnt);
    }
}
@Slf4j
public class Thread2 implements Runnable {
    @Override
    public void run() {
        Counter.initCounter();
        while (Counter.counter.get() > 0) {
            Counter.minus();
            log.info("{}当前a值为:{}", Thread.currentThread().getName(), Counter.counter.get());
        }
    }
}

这个例子中,每个线程都会保留一份属于自己的变量,相互之间不共享。

但是有一个问题,ThreadLocal变量声明后,默认get返回的是null,而不是0,我们有时候需要它能有默认值,那么就应该使用自定义的ThreadLocal类:

public class ThreadLocalNew<T> extends ThreadLocal {
    @Override
    protected Object initialValue() {
        return 10;
    }
}
public class Counter {
    public static ThreadLocalNew<Integer> counter = new ThreadLocalNew<>();

    public static void minus(){
        Integer cnt = (Integer) counter.get();
        counter.set(--cnt);
    }
}
@Slf4j
public class Thread2 implements Runnable {

    @Override
    public void run() {
        while ((Integer)Counter.counter.get() > 0) {
            Counter.minus();
            log.info("{}当前a值为:{}", Thread.currentThread().getName(), Counter.counter.get());
        }
    }
}

相关文章

网友评论

      本文标题:ThreadLocal的使用

      本文链接:https://www.haomeiwen.com/subject/gxvjwhtx.html