美文网首页
ThreadLocal(一)

ThreadLocal(一)

作者: 50e383299c68 | 来源:发表于2018-01-24 19:54 被阅读0次
    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不是一个。

    相关文章

      网友评论

          本文标题:ThreadLocal(一)

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