ThreadLocal问题

时间:2017-06-25 14:29:49

标签: 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 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吗?

2 个答案:

答案 0 :(得分:2)

您的问题与ThreadLocal无关。你的问题是这不是一个原子操作:

++custID;

可能发生的情况是,主题A看到custID == 1,将其存储在ThreadLocal对象的自己的bin中,并分配custID=2。同时,线程B也看到custID == 1并且它做同样的事情。

您需要某种保护 - 互斥锁或AtomicInteger,以确保一次只有一个线程尝试获取新的custID值。

P.S。:我会尽量避免在新代码中使用ThreadLocalThreadLocal的主要用途是将使用static变量的旧代码从单线程转换为多线程。但是,如果您正在编写新代码,那么您应该尽力避免staticstatic会使您的代码难以维护,并且非常难以正确测试。

在小型一次性课程中使用static并没有错,只不过它会教你一个坏习惯。

答案 1 :(得分:1)