欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ThreadLocal 使用及原理

程序员文章站 2022-05-14 18:00:08
...
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。这样就隔离了多个线程对数据的数据共享

当线程并发时,使用ThreadLocal在保证每个线程拥有自己的独立对象,线程间互不影响。

原理:
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。我们自己就可以提供一个简单的实现版本:

区别:
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

使用:
public class MyThreadLocal {
    //定义了一个ThreadLocal变量,用来保存int或Integer数据
    private ThreadLocal<Integer> tl = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    public Integer getNextNum() {
        //将tl的值获取后加1,并更新设置t1的值
        tl.set(tl.get() + 1);
        return tl.get();
    }
}

* 测试线程
*/
public class TestThread extends Thread {
    private MyThreadLocal tlt = new MyThreadLocal();

    public TestThread(MyThreadLocal tlt) {
        this.tlt = tlt;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + "\t" + tlt.getNextNum());
        }
    }
}

public class Test {
    public static void main(String[] args) {
        MyThreadLocal tlt = new MyThreadLocal();
        Thread t1 = new TestThread(tlt);
        Thread t2 = new TestThread(tlt);
        Thread t3 = new TestThread(tlt);
        Thread t4 = new TestThread(tlt);
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

可以看出,三个线程各自独立编号,互不影响:
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-0 3
Thread-1 3
Thread-2 1
Thread-3 1
Thread-2 2
Thread-3 2
Thread-2 3
Thread-3 3


Process finished with exit code 0


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private static ThreadLocal DATE_FORMAT_NUM  = new ThreadLocal() {  
protected synchronized SimpleDateFormat initialValue() {  
return new SimpleDateFormat("yyyyMMddHHmmss");  
}  
}; 
相关标签: 线程 ThreadLocal