ThreadLocal向线程提供包装对象的独占副本。我正在执行一个方案
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();
}
}线程本地应该为每个客户获得唯一的价值,但是当我运行上面的场景时,它会生成
带有客户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这种行为正确吗?
发布于 2017-06-25 14:37:47
您的问题与ThreadLocal无关。您的问题是,这不是原子操作:
++custID;可以发生的情况是,线程A看到custID == 1,将其存储到ThreadLocal objet中自己的bin中,并分配custID=2。同时,线程B也会看到custID == 1,它也会做同样的事情。
您需要某种保护--互斥锁或AtomicInteger,以确保每次只有一个线程尝试获得一个新的custID值。
P.S.:我会尽量避免在新代码中使用ThreadLocal。ThreadLocal的主要用途是将使用static变量的旧代码从单线程转换为多线程。但是,如果您正在编写新代码,首先您应该尽力避免static。static使您的代码很难维护,很难进行正确的测试。
在小的、丢弃的程序中使用static没有什么错,只是它会教你一个坏习惯。
发布于 2017-06-25 14:42:04
尝试使用AtomicInteger作为您的计数器。https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
https://stackoverflow.com/questions/44747349
复制相似问题