java线程类:ThreadLocal的理解

1.什么是ThreadLocal变量?

解答一:ThreadLocal是Java里一种特殊的变量。每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量,竞争条件被 彻底消除了。它是为创建代价高昂的对象获取线程安全的好方法,比如你可以用ThreadLocal让SimpleDateFormat变成线程安全的,因 为那个类创建代价高昂且每次调用都需要创建不同的实例所以不值得在局部范围使用它,如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通 过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。线程局部变量的另一个不错的例子是 ThreadLocalRandom类,它在多线程环境中减少了创建代价高昂的Random对象的个数。(来源:https://www.cnblogs.com/Jansens520/p/8624708.html)

解答二:ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。(来源:https://www.jianshu.com/p/98b68c97df9b)

个人理解:ThreadLocal变量其实就是当每个线程的run()方法【线程执行体】用到他的时候,他会基于当前线程去拷贝一个变量,而不再原有的变量上直接操作。以达到数据隔离的目的。结合第一种解答,可知使用threadLocal的优点。

2.ThreadLocal底层原理:

参看博客:https://www.jianshu.com/p/98b68c97df9b(此文写的很好)

3.应用小实例:多个用户向银行存钱:

package com.springboot.thread;


/**
 * ThreadLocal提供线程的局部变量,即为使用相同变量的每个线程维护一个该变量的副本,
 * 当某些数据是以线程作为作用域并且不同线程具有不同的数据副本的时候,可以考虑使用ThreadLocal。
 * 比如数据库连接:connection,每个请求处理线程都需要,但又互不影响,就是ThreadLocal的实现
 * */
public class TestThreadLocal {
    /*模拟银行的多个客户存钱转账业务*/
    public static class Bank{
        /*初始时的银行的账户余额*/
        ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
            @Override
            protected Integer initialValue() {
                return 0;
            }
        };

        /*存钱*/
        public void saveMoney(Integer money) {
            this.threadLocal.set(this.threadLocal.get()+money);
        }

        /*取款*/
        public Integer getMoney(Integer money){
            this.threadLocal.set(this.threadLocal.get()-money);
            return money;
        }

        /*获取账户余额*/

        public Integer get(){
            return this.threadLocal.get();
        }
    }

    static class Transfer implements  Runnable{
        Bank  bank;
        public Transfer(Bank bank){
            this.bank= bank;
        }

        @Override
        public void run() {
            /*模拟向自己的账户里存钱10次*/
            for (int i=0;i<10;i++){
                bank.saveMoney(10);
                System.out.println("用户:"+Thread.currentThread().getName()+":账户余额为:" + bank.get());
            }
        }
    }


    public static void main(String[] args) {
        Bank bank = new Bank();
        Transfer transfer = new Transfer(bank);
        Thread thread1 = new Thread(transfer,"客户一");
        Thread thread2 = new Thread(transfer,"客户二");
        thread1.start();
        thread2.start();
    }


}

4.运行结果:

用户:客户一:账户余额为:10
用户:客户一:账户余额为:20
用户:客户一:账户余额为:30
用户:客户一:账户余额为:40
用户:客户一:账户余额为:50
用户:客户一:账户余额为:60
用户:客户一:账户余额为:70
用户:客户一:账户余额为:80
用户:客户一:账户余额为:90
用户:客户一:账户余额为:100
用户:客户二:账户余额为:10
用户:客户二:账户余额为:20
用户:客户二:账户余额为:30
用户:客户二:账户余额为:40
用户:客户二:账户余额为:50
用户:客户二:账户余额为:60
用户:客户二:账户余额为:70
用户:客户二:账户余额为:80
用户:客户二:账户余额为:90
用户:客户二:账户余额为:100

5.参考文章:

(1).https://www.jianshu.com/p/98b68c97df9b[重点推荐]

(2).https://www.cnblogs.com/darendu/p/11043658.html

(3).https://www.jianshu.com/p/3c5d7f09dfbd

(4).https://www.cnblogs.com/Jansens520/p/8624708.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值