《多线程》第9节:ThreadLocal类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《多线程》第9节:ThreadLocal类相关的知识,希望对你有一定的参考价值。


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

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

class A
ThreadLocal<Integer> x = new ThreadLocal<Integer>();

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

【例14_20 ThreadLocal类】

Exam14_20.java

class Account
//能够动用的最大账户金额
ThreadLocal<Integer> maxValue = new ThreadLocal<Integer>();
Account(Integer maxValue)
this.maxValue.set(maxValue);

synchronized void printMaxValue()
System.out.print(Thread.currentThread().getName());
System.out.println("能够动用的最大金额:"+maxValue.get());


class AccountThread extends Thread
Account account;
Integer ownValue;//自身能动用的最大账户金额
AccountThread(String name,Account account,Integer ownValue)
super(name);
this.account = account;
this.ownValue = ownValue;

@Override
public void run()
account.maxValue.set(ownValue);//①
account.printMaxValue();


public class Exam14_20
public static void main(String[] args)
Account account = new Account(60000);
System.out.println("主线程中a对象的maxValue值:"+account.maxValue.get());
new AccountThread("总经理",account, 1000000).start();
new AccountThread("副总经理",account,500000).start();

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

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

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

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

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

以上是关于《多线程》第9节:ThreadLocal类的主要内容,如果未能解决你的问题,请参考以下文章

Java 线程系列ThreadLocal进阶解析

ThreadLocal详解(实现多线程同步访问变量)

Java多线程——ThreadLocal类

多线程:线程相关类

《多线程》第7节:线程组

蚂蚁课堂(每特学院)-2期