ThreadLocal

ThreadLocal

先看不使用ThreadLocal的例子:

package ch1.base.threadlocal;

public class NoThreadLocal {
    static Integer count = new Integer(1);

    public static class TestTask implements Runnable{
        int id;
        public TestTask(int id){
            this.id =id;
        }

        public void run(){
            System.out.println(Thread.currentThread().getName()+":start");
            count = count+1;
            System.out.println(Thread.currentThread().getName()+":"+count);
        }
    }

    //运行三个线程
    public void StartThreadArray(){
        Thread[] runs = new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i] = new Thread(new TestTask(i));
        }

        for(int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }

    public static void main(String[] args) {
        NoThreadLocal noThreadLocal = new NoThreadLocal();
        noThreadLocal.StartThreadArray();
    }
}

/*
输出:
Thread-1:start
Thread-0:start
Thread-0:3
Thread-2:start
Thread-1:2
Thread-2:4

Process finished with exit code 0
 */

再来看使用ThreadLocal的例子

package ch1.base.threadlocal;


//演示ThreadLocal的使用
public class UseThreadLocal {

    private static ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };

    private static ThreadLocal<String> stringThreadLocal;

    //测试线程,线程的工作是将ThreadLocal变量的值变化,并写回,看看线程之间是否会互相影响
    public static class TestThread implements Runnable{
        int id;
        public TestThread(int id){
            this.id = id;
        }

        public void run(){
            System.out.println(Thread.currentThread().getName()+": start");
            Integer s = intLocal.get();
            s=s+id;
            intLocal.set(s);
            System.out.println(Thread.currentThread().getName()+":"+intLocal.get());

        //  intLocal.remove();
        }
    }

    //运行三个线程
    public void runThreadThree(){
        Thread[] runs = new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i] = new Thread(new TestThread(i));
        }
        for(int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }

    public static void main(String[] args) {
        UseThreadLocal test = new UseThreadLocal();
        test.runThreadThree();
    }
}

/*
Thread-0: start
Thread-1: start
Thread-2: start
Thread-0:1
Thread-1:2
Thread-2:3

Process finished with exit code 0
 */

基础
ThreadLocal是一个关于创建线程局部变量的类。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

有一个误区是ThreadLocal的目的是为了解决多线程访问资源时的共享问题 但ThreadLocal 并不解决多线程 共享 变量的问题。既然变量不共享,那就更谈不上同步的问题。

理解
ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String 类型变量),在不同的 Thread 中有不同的副本(实际是不同的实例)。这里有几点需要注意

因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来
既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题
既无共享,何来同步问题,又何来解决同步问题一说?
那 ThreadLocal 到底解决了什么问题,又适用于什么样的场景?

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

核心意思是

ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。这让我想到了Js中的一个特性:闭包.闭包下的所有变量都是只属于自己的,而ThreadLocal就是只属于线程自己的对象. 另外,该场景下,并非必须使用 ThreadLocal ,其它方式完全可以实现同样的效果,只是 ThreadLocal 使得实现更简洁。
参考:https://blog.csdn.net/qq_30054997/article/details/81515668

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Remember me for centuries And I can't stop until ...
    宿大人有大梦想阅读 670评论 0 0
  • 竞争日益激烈的现代社会,要使自己有一席之地,要独占鳌头,鹤立鸡群,一般的做法,是不断努力提高自己的竞争力。竞争力指...
    康德_326阅读 221评论 0 0
  • 小成就:《沟通的艺术》共读活动40天学车(08/15-08/20)香港之行(08/28-08/30)电影:《全民情...
    汐米阅读 181评论 0 0
  • 你信吗? 信。 信就行。 什么意思? 有种做梦,就要有种不醒。 醒不醒由不得我呀! 这是现实。 怎么办? 投入一场...
    灰鞋阅读 179评论 0 2