ThreadLocal(一)

2018-01-24  本文已影响0人  50e383299c68
  1. 概述
    官方说明:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code 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).

翻译过来的大概意思是:ThreadLocal类用来提供线程内部的局部变量。这些变量和线程内其他的变量不同。ThreadLocal类型的变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程里的变量独立于其他线程内的变量。ThreadLocal实例通常都是private static类型。
很多文章将ThreadLocal与线程同步机制混为一谈,特别注意的是ThreadLocal与线程同步无关,并不是为了解决多线程共享变量问题!

  1. 使用示例
/**
 * 序列号生成器.内部使用ThreadLocal<Integer>存储序列号
 */ 
public class SequenceNumber {
    /**
     * ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
     */
    private ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
        @Override
        public Integer initialValue() {
            return 0;
        }
    };

    /**
     * ②获取下一个序列值
     * @return
     */
    public int getNextNum() {
        seqNum.set(seqNum.get() + 1);
        return seqNum.get();
    }
    
    public void remove() {
        seqNum.remove();
    }
}

public class TestClient implements Runnable {
    private SequenceNumber sn;

    public TestClient(SequenceNumber sn) {
        super();
        this.sn = sn;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            // ④每个线程打出3个序列值
            System.out.println("thread[" + Thread.currentThread().getName()
                    + "] sn[" + sn.getNextNum() + "]");
        }
    }

    public static void main(String[] args) {
        SequenceNumber sn = new SequenceNumber();
        // ③ 3个线程共享sn,各自产生序列号
        TestClient t1 = new TestClient(sn);
        TestClient t2 = new TestClient(sn);
        TestClient t3 = new TestClient(sn);
        new Thread(t1).start();
        new Thread(t2).start();
        new Thread(t3).start();
    }

上面的代码TestClient的测试函数main,生成了三个线程,三个线程共享一个序列号生成对象。从多线程的角度考虑,三个线程运行产生的序列号应该各不相同。下面看运行结果:
thread[Thread-0] sn[1]
thread[Thread-0] sn[2]
thread[Thread-0] sn[3]
thread[Thread-1] sn[1]
thread[Thread-1] sn[2]
thread[Thread-1] sn[3]
thread[Thread-2] sn[1]
thread[Thread-2] sn[2]
thread[Thread-2] sn[3]
三个线程生成的序列号是相同的1到3。
这说明虽然在构造TestClient对象时用的同一个SequenceNumber对象。但是在使用SequenceNumber对象时,SequenceNumber对象里面的ThreadLocal<Integer> seqNum不是一个。

上一篇下一篇

猜你喜欢

热点阅读