还不会使用Java ThreadLocal落后了吧!

Java中的ThreadLocal类容许咱们建立只能被同一个线程读写的变量。所以,若是一段代码含有一个ThreadLocal变量的引用,即便两个线程同时执行这段代码,它们也没法访问到对方的ThreadLocal变量。java

如何建立ThreadLocal变量

如下代码展现了如何建立一个ThreadLocal变量:面试

private ThreadLocal myThreadLocal = new ThreadLocal();

咱们能够看到,经过这段代码实例化了一个ThreadLocal对象。咱们只须要实例化对象一次,而且也不须要知道它是被哪一个线程实例化。虽然全部的线程都能访问到这个ThreadLocal实例,可是每一个线程却只能访问到本身经过调用ThreadLocal的set()方法设置的值。即便是两个不一样的线程在同一个ThreadLocal对象上设置了不一样的值,他们仍然没法访问到对方的值。算法

如何访问ThreadLocal变量

一旦建立了一个ThreadLocal变量,你能够经过以下代码设置某个须要保存的值:spring

myThreadLocal.set("A thread local value”);

能够经过下面方法读取保存在ThreadLocal变量中的值:数据库

String threadLocalValue = (String) myThreadLocal.get();

get()方法返回一个Object对象,set()对象须要传入一个Object类型的参数。设计模式

为ThreadLocal指定泛型类型

咱们能够建立一个指定泛型类型的ThreadLocal对象,这样咱们就不须要每次对使用get()方法返回的值做强制类型转换了。下面展现了指定泛型类型的ThreadLocal例子:缓存

private ThreadLocal myThreadLocal = new ThreadLocal<String>();

如今咱们只能往ThreadLocal对象中存入String类型的值了。数据结构

而且咱们从ThreadLocal中获取值的时候也不须要强制类型转换了。多线程

如何初始化ThreadLocal变量的值

因为在ThreadLocal对象中设置的值只能被设置这个值的线程访问到,线程没法在ThreadLocal对象上使用set()方法保存一个初始值,而且这个初始值能被全部线程访问到。并发

可是咱们能够经过建立一个ThreadLocal的子类而且重写initialValue()方法,来为一个ThreadLocal对象指定一个初始值。就像下面代码展现的那样:

private ThreadLocal myThreadLocal = new ThreadLocal<String>() {

    @Override
    protected String initialValue() {
        return "This is the initial value";
    }

};

一个完整的ThreadLocal例子

下面是一个完整的可执行的ThreadLocal例子:

public class ThreadLocalExample {

    public static class MyRunnable implements Runnable {

        private ThreadLocal threadLocal = new ThreadLocal();

        @Override
        public void run() {
            threadLocal.set((int) (Math.random() * 100D));
            try {
            Thread.sleep(2000);
            } catch (InterruptedException e) {

            }
            System.out.println(threadLocal.get());
        }
    }

    public static void main(String[] args) {
         MyRunnable sharedRunnableInstance = new MyRunnable();
         Thread thread1 = new Thread(sharedRunnableInstance);
         Thread thread2 = new Thread(sharedRunnableInstance);
         thread1.start();
         thread2.start();
    }

}

上面的例子建立了一个MyRunnable实例,并将该实例做为参数传递给两个线程。两个线程分别执行run()方法,而且都在ThreadLocal实例上保存了不一样的值。若是它们访问的不是ThreadLocal对象而且调用的set()方法被同步了,则第二个线程会覆盖掉第一个线程设置的值。可是,因为它们访问的是一个ThreadLocal对象,所以这两个线程都没法看到对方保存的值。也就是说,它们存取的是两个不一样的值。

关于InheritableThreadLocal

InheritableThreadLocal类是ThreadLocal类的子类。ThreadLocal中每一个线程拥有它本身的值,与ThreadLocal不一样的是,InheritableThreadLocal容许一个线程以及该线程建立的全部子线程均可以访问它保存的值。

最后

私信回复 资料 领取一线大厂Java面试题总结+阿里巴巴泰山手册+各知识点学习思惟导+一份300页pdf文档的Java核心知识点总结!

这些资料的内容都是面试时面试官必问的知识点,篇章包括了不少知识点,其中包括了有基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。
file

相关文章
相关标签/搜索