• 第十四章《多线程》第9节:ThreadLocal类


    如果多个线程共用一个对象,那么这个对象的属性值对于这些线程都是相同的。例如有一个a对象,它有一个x属性,如果x属性的值是1,那么对于任何一个线程而言,a对象的x属性都是1。但有些情况下,需要让一个对象的属性对于不同的线程具有不同的值,也就是说,a对象的x属性的值在一个线程那里是1,在另一个线程那里是2。

    使用ThreadLocal类就能实现这样需求。如果对象的属性类型是Integer,那么可以在定义类时定义一个ThreadLocal类的对象,并且以指定ThreadLocal的类型参数为Integer,例如:

    1. class A{
    2.     ThreadLocal x = new ThreadLocal();
    3. }

    以上代码中x属性就是一个ThreadLocal类对象,它的内部包装了一个Integer类对象,如果多个线程共享A类对象a,那么这个Integer的值可以在不同的线程中被指定为不同的值。这个ThreadLocal类定义的属性很有用处,例如有一个Account类表示账户,一个企业中,总经理能够一次性动用账户中一百万元,而副总经理只能一次性动用账户中的五十万元,那么Account中能够被动用的最大金额就可以用ThreadLocal类来定义,下面的【例14_20】就展示了ThreadLocal类的使用方法。

    【例14_20 ThreadLocal类】

    Exam14_20.java

    1. class Account{
    2. //能够动用的最大账户金额
    3. ThreadLocal maxValue = new ThreadLocal();
    4. Account(Integer maxValue){
    5. this.maxValue.set(maxValue);
    6. }
    7. synchronized void printMaxValue(){
    8. System.out.print(Thread.currentThread().getName());
    9. System.out.println("能够动用的最大金额:"+maxValue.get());
    10. }
    11. }
    12. class AccountThread extends Thread{
    13. Account account;
    14. Integer ownValue;//自身能动用的最大账户金额
    15. AccountThread(String name,Account account,Integer ownValue){
    16. super(name);
    17. this.account = account;
    18. this.ownValue = ownValue;
    19. }
    20. @Override
    21. public void run() {
    22. account.maxValue.set(ownValue);//①
    23. account.printMaxValue();
    24. }
    25. }
    26. public class Exam14_20 {
    27. public static void main(String[] args) {
    28. Account account = new Account(60000);
    29. System.out.println("主线程中a对象的maxValue值:"+account.maxValue.get());
    30. new AccountThread("总经理",account, 1000000).start();
    31. new AccountThread("副总经理",account,500000).start();
    32. }
    33. }

    【例14_20】中,Account类表示账户,账户最大可动用金额由maxValue属性来表示。可以看出:maxValue属性的类型是ThreadLocal,这个ThreadLocal类对象中包装了一个Integer对象,这个对象才是真正可动用的最大账户金额。main()方法中创建了一个Account类的对象account,并设置其maxValue属性的值为60000。以account为构造方法创建出的两个线程分别表示总经理和副总经理。这两个线程开始运行后首先设置自身可动用的最大金额为1000000和500000,之后再打印自身可动用金额的数值。【例14_20】的运行结果如图14-19所示。

    图14-19【例14_20】运行结果

    从图14-19可以看出:每个线程中account的maxValue值各不相同。之所以能够做到同一个对象的相同属性具有不同的值,这是因为ThreadLocal类的属性在内存中为每个线程中都创建了副本,其中主线程也是一个线程,因此这个maxValue属性具有三个副本,分别属于主线程、总经理和副总经理。特别需要强调:只有在线程开始运行后,ThreadLocal类的属性才会被创建副本,因此语句①是在run()方法中设置每个线程的maxValue值而不是在Account构造方法中进行设置。如果程序员在构造方法中进行设置,那么不会出现maxValue的三个副本。

    除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

  • 相关阅读:
    [应用推荐]Web Scraper——轻量数据爬取利器
    LoRaWan模块应用于智慧城市景观灯
    SpringSecurity的OAuth2的授权服务器配置
    树莓派4B(Ubuntu20.04)使用LCD1602液晶屏开机自动显示IP及其他信息
    多态
    经典面试题-平时用的测试框架是什么?pytest框架下怎么入参?
    AD20 ~PCB封装库的制作
    在一台电脑上安装多个python版本(小白教程)
    在springboot工程中修改使用quartz创建的定时任务
    3个管理误区,新晋管理者一定要避免!
  • 原文地址:https://blog.csdn.net/shalimu/article/details/128111633