ThreadLocal的使用

threadLocal是线程封闭的一种实现。

线程封闭:当访问共享的可变数据,通常需要使用同步。一种避免使用同步的方法就是不共享。如果单线程内访问数据,就不需要同步。这种技术就是线程封闭。局部变量和ThreadLocal就是这种机制的一种实现。

其实就是每个thread有自己的副本,不共享。

下面看下代码(也是参考了网上其他人的):

public class SequenceNumber {

    //①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
//    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){
//        public Integer initialValue(){
//            return 0;
//        }
//    };

    //也可以用下面这个方法
    private static ThreadLocal<Integer> seqNum = ThreadLocal.withInitial(() -> 0);

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

    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);
        t1.start();
        t2.start();
        t3.start();
    }

    private static class TestClient extends Thread{
        private SequenceNumber sn;

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

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

结果:

Connected to the target VM, address: 'javadebug', transport: 'shared memory'
thread[Thread-0] sn[1]
thread[Thread-0] sn[2]
thread[Thread-0] sn[3]
thread[Thread-1] sn[1]
thread[Thread-2] sn[1]
thread[Thread-2] sn[2]
thread[Thread-2] sn[3]
thread[Thread-1] sn[2]
thread[Thread-1] sn[3]

线程不安全版:

package ThreadLocalTest.threadLocalSequenceNumber;

/**
 * @author huql
 * @date 2021/7/24 21:18
 * @comments:
 */
public class SequenceNumber {

    private static Integer seqNum = 0;

//    ②获取下一个序列值. 线程不安全
    public int getNextNum(){
        seqNum = seqNum + 1;
        return seqNum;
    }

    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);
        t1.start();
        t2.start();
        t3.start();
    }

    private static class TestClient extends Thread{
        private SequenceNumber sn;

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

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

结果:

ThreadLocalTest.threadLocalSequenceNumber.SequenceNumber
Connected to the target VM, address: 'javadebug', transport: 'shared memory'
thread[Thread-0] sn[1]
thread[Thread-2] sn[3]
thread[Thread-2] sn[4]
thread[Thread-2] sn[5]
thread[Thread-1] sn[2]
thread[Thread-1] sn[6]
thread[Thread-1] sn[7]
thread[Thread-0] sn[8]
thread[Thread-0] sn[9]

第二个例子:

public class ThreadLocalStudy {

    static ThreadLocal<String> localLocalVar = new ThreadLocal<String>();

    static void printString(String str) {
        //打印本地变量
        System.out.println(str + ":" + localLocalVar.get());
        //移除本地变量
        localLocalVar.remove();
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localLocalVar.set("localLocalVar1");
                //调用打印方法
                printString("thread1");
                printString("after remove : " + localLocalVar.get());
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localLocalVar.set("localLocalVar2");
                //调用打印方法
                printString("thread2");
                //打印本地变量
                printString("after remove : " + localLocalVar.get());
            }
        });

        t1.start();
        t2.start();
    }
}

输出:

Connected to the target VM, address: 'javadebug', transport: 'shared memory'
thread1:localLocalVar1
after remove : null:null
thread2:localLocalVar2
after remove : null:null
Disconnected from the target VM, address: 'javadebug', transport: 'shared memory'

参考:
https://zhuanlan.zhihu.com/p/390527514
https://cloud.tencent.com/developer/article/1657723
https://www.jianshu.com/p/537167d42c82

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值