Java 本地问题

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

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();
}

}
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