如果多个线程共用一个对象,那么这个对象的属性值对于这些线程都是相同的。例如有一个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所示。
图14-19【例14_20】运行结果
从图14-19可以看出:每个线程中account的maxValue值各不相同。之所以能够做到同一个对象的相同属性具有不同的值,这是因为ThreadLocal类的属性在内存中为每个线程中都创建了副本,其中主线程也是一个线程,因此这个maxValue属性具有三个副本,分别属于主线程、总经理和副总经理。特别需要强调:只有在线程开始运行后,ThreadLocal类的属性才会被创建副本,因此语句①是在run()方法中设置每个线程的maxValue值而不是在Account构造方法中进行设置。如果程序员在构造方法中进行设置,那么不会出现maxValue的三个副本。
本文字版教程还配有更详细的视频讲解,小伙伴们可以点击这里观看。
标签:account,Account,maxValue,ThreadLocal,线程,第十四章,多线程,属性 From: https://blog.51cto.com/mugexuetang/5983951