Java 本地问题
ThreadLocal向线程提供已包装对象的独占副本。 我正在执行一个场景Java 本地问题,java,multithreading,thread-local,Java,Multithreading,Thread Local,ThreadLocal向线程提供已包装对象的独占副本。 我正在执行一个场景 public class CustomerThread extends Thread{ static Integer custId =0; private static ThreadLocal t1 = new ThreadLocal(){ protected Integer initialValue() { return ++custId; } }; public C
public class CustomerThread extends Thread{
static Integer custId =0;
private static ThreadLocal t1 = new ThreadLocal(){
protected Integer initialValue() {
return ++custId;
}
};
public CustomerThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+ " executing with customer Id : "+t1.get());
}
}
public class ThreadLocalDemo {
public static void main(String[] args) {
CustomerThread c1 = new CustomerThread("A");
CustomerThread c2 = new CustomerThread("B");
CustomerThread c3 = new CustomerThread("C");
CustomerThread c4 = new CustomerThread("D");
CustomerThread c5 = new CustomerThread("E");
CustomerThread c6 = new CustomerThread("F");
CustomerThread c7 = new CustomerThread("G");
CustomerThread c8 = new CustomerThread("H");
CustomerThread c9 = new CustomerThread("I");
CustomerThread c10 = new CustomerThread("J");
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
c7.start();
c8.start();
c9.start();
c10.start();
}
}
Threadlocal应该为每个客户获得唯一的价值,但当我运行上述场景时,它有时会产生
正在执行一个客户Id为1的
B使用客户Id执行:1
D使用客户Id执行:3
C使用客户Id执行:2
E使用客户Id执行:4
F使用客户Id执行:5
G使用客户Id执行:6
H使用客户Id执行:7
我的客户Id为:8
J使用客户Id执行:9
这里A和B得到相同的值
有人能解释一下w.r.t ThreadLocal的这种行为是否正确吗?您的问题与
ThreadLocal
无关。您的问题是,这不是一个原子操作:
++custID;
可能发生的情况是,线程A看到custID==1
,将其存储到ThreadLocal
对象中自己的bin中,并分配custID=2
。同时,线程B也看到custID==1
,它做了同样的事情
您需要某种保护——互斥锁或AtomicInteger
,以确保一次只有一个线程尝试获取新的custID
值
注意:我会尽量避免在新代码中使用
ThreadLocal
。ThreadLocal
的主要用途是将使用static
变量的旧代码从单线程转换为多线程。但是,如果您正在编写新代码,首先应该尽最大努力避免静态<代码>静态
使代码很难维护,也很难正确测试
在小而一次性的程序中使用
静态
没有什么错,只是它会教你一个坏习惯。你的问题与线程本地
无关。您的问题是,这不是一个原子操作:
++custID;
可能发生的情况是,线程A看到custID==1
,将其存储到ThreadLocal
对象中自己的bin中,并分配custID=2
。同时,线程B也看到custID==1
,它做了同样的事情
您需要某种保护——互斥锁或AtomicInteger
,以确保一次只有一个线程尝试获取新的custID
值
注意:我会尽量避免在新代码中使用
ThreadLocal
。ThreadLocal
的主要用途是将使用static
变量的旧代码从单线程转换为多线程。但是,如果您正在编写新代码,首先应该尽最大努力避免静态<代码>静态
使代码很难维护,也很难正确测试
在小而一次性的程序中使用
静态
没有什么错,只是它会教你一个坏习惯。尝试使用原子整数
作为计数器。
尝试对计数器使用
AtomicInteger
。