ThreadLocal 测试类
@Slf4j
public class ThreadTest {
public static void main(String[] args) {
test2();
}
//线程安全
public static void test2() {
for(int i = 0; i < 10; i++) {
log.info("begin:"+i);
new Thread(()->{
try {
method2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
log.info("end:"+i);
}
}
public static void method2() throws InterruptedException {
log.info(Thread.currentThread().getName()+"==>"+" begin");
ThreadLocalMap.put("TTTTTTTT",Thread.currentThread().getName());
Thread.sleep(1000);
log.info(Thread.currentThread().getName()+"==>"+ThreadLocalMap.get("TTTTTTTT"));
}
}
测试结果:同一个线程获取到自己当初put的value值
2018-12-19 17:38:30,609 INFO ScheduledExecutorServiceTest:23 begin:0
2018-12-19 17:38:30,890 INFO ScheduledExecutorServiceTest:31 end:0
2018-12-19 17:38:30,896 INFO ScheduledExecutorServiceTest:23 begin:1
2018-12-19 17:38:30,895 INFO ScheduledExecutorServiceTest:37 Thread-0==> begin
2018-12-19 17:38:30,902 INFO ScheduledExecutorServiceTest:31 end:1
2018-12-19 17:38:30,903 INFO ScheduledExecutorServiceTest:37 Thread-1==> begin
2018-12-19 17:38:30,917 INFO ScheduledExecutorServiceTest:23 begin:2
2018-12-19 17:38:30,926 INFO ScheduledExecutorServiceTest:31 end:2
2018-12-19 17:38:30,927 INFO ScheduledExecutorServiceTest:37 Thread-2==> begin
2018-12-19 17:38:30,929 INFO ScheduledExecutorServiceTest:23 begin:3
2018-12-19 17:38:30,938 INFO ScheduledExecutorServiceTest:31 end:3
2018-12-19 17:38:30,941 INFO ScheduledExecutorServiceTest:37 Thread-3==> begin
2018-12-19 17:38:30,944 INFO ScheduledExecutorServiceTest:23 begin:4
2018-12-19 17:38:30,950 INFO ScheduledExecutorServiceTest:31 end:4
2018-12-19 17:38:30,950 INFO ScheduledExecutorServiceTest:37 Thread-4==> begin
2018-12-19 17:38:30,953 INFO ScheduledExecutorServiceTest:23 begin:5
2018-12-19 17:38:30,966 INFO ScheduledExecutorServiceTest:31 end:5
2018-12-19 17:38:30,966 INFO ScheduledExecutorServiceTest:37 Thread-5==> begin
2018-12-19 17:38:30,969 INFO ScheduledExecutorServiceTest:23 begin:6
2018-12-19 17:38:30,980 INFO ScheduledExecutorServiceTest:31 end:6
2018-12-19 17:38:30,984 INFO ScheduledExecutorServiceTest:23 begin:7
2018-12-19 17:38:30,980 INFO ScheduledExecutorServiceTest:37 Thread-6==> begin
2018-12-19 17:38:30,990 INFO ScheduledExecutorServiceTest:37 Thread-7==> begin
2018-12-19 17:38:30,990 INFO ScheduledExecutorServiceTest:31 end:7
2018-12-19 17:38:31,000 INFO ScheduledExecutorServiceTest:23 begin:8
2018-12-19 17:38:31,006 INFO ScheduledExecutorServiceTest:31 end:8
2018-12-19 17:38:31,009 INFO ScheduledExecutorServiceTest:23 begin:9
2018-12-19 17:38:31,007 INFO ScheduledExecutorServiceTest:37 Thread-8==> begin
2018-12-19 17:38:31,013 INFO ScheduledExecutorServiceTest:37 Thread-9==> begin
2018-12-19 17:38:31,012 INFO ScheduledExecutorServiceTest:31 end:9
2018-12-19 17:38:31,911 INFO ScheduledExecutorServiceTest:40 Thread-0==>Thread-0
2018-12-19 17:38:31,922 INFO ScheduledExecutorServiceTest:40 Thread-1==>Thread-1
2018-12-19 17:38:31,934 INFO ScheduledExecutorServiceTest:40 Thread-2==>Thread-2
2018-12-19 17:38:31,947 INFO ScheduledExecutorServiceTest:40 Thread-3==>Thread-3
2018-12-19 17:38:31,959 INFO ScheduledExecutorServiceTest:40 Thread-4==>Thread-4
2018-12-19 17:38:31,972 INFO ScheduledExecutorServiceTest:40 Thread-5==>Thread-5
2018-12-19 17:38:31,993 INFO ScheduledExecutorServiceTest:40 Thread-6==>Thread-6
2018-12-19 17:38:31,996 INFO ScheduledExecutorServiceTest:40 Thread-7==>Thread-7
2018-12-19 17:38:32,016 INFO ScheduledExecutorServiceTest:40 Thread-8==>Thread-8
2018-12-19 17:38:32,020 INFO ScheduledExecutorServiceTest:40 Thread-9==>Thread-9
HashMap测试
@Slf4j
public class ThreadTest {
public static void main(String[] args) {
test1();
}
// HashMap线程不安全
public static void test1() {
Map<String,String> map = new HashMap<>();
for(int i = 0; i < 10; i++) {
log.info("begin:"+i);
new Thread(()->{
try {
method1(map);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
log.info("end:"+i);
}
}
public static void method1(Map<String,String> map) throws InterruptedException {
log.info(Thread.currentThread().getName()+"==>"+" begin");
//线程在执行过程中,没有执行完method1方法时,被其他线程抢cpu,则map的key对应的value值被重新赋值
map.put("TTTTTTTT",Thread.currentThread().getName());
Thread.sleep(1000);
//从而,当前线程有可能获取不到当初put的value值,从而导致线程安全问题
log.info(Thread.currentThread().getName()+"==>"+map.get("TTTTTTTT"));
}
}
测试结果:线程value值被覆盖了
2018-12-19 18:08:22,078 INFO ThreadTest:46 begin:0
2018-12-19 18:08:22,470 INFO ThreadTest:54 end:0
2018-12-19 18:08:22,474 INFO ThreadTest:46 begin:1
2018-12-19 18:08:22,490 INFO ThreadTest:54 end:1
2018-12-19 18:08:22,498 INFO ThreadTest:46 begin:2
2018-12-19 18:08:22,499 INFO ThreadTest:60 Thread-1==> begin
2018-12-19 18:08:22,498 INFO ThreadTest:60 Thread-0==> begin
2018-12-19 18:08:22,513 INFO ThreadTest:60 Thread-2==> begin
2018-12-19 18:08:22,510 INFO ThreadTest:54 end:2
2018-12-19 18:08:22,539 INFO ThreadTest:46 begin:3
2018-12-19 18:08:22,547 INFO ThreadTest:54 end:3
2018-12-19 18:08:22,555 INFO ThreadTest:46 begin:4
2018-12-19 18:08:22,560 INFO ThreadTest:54 end:4
2018-12-19 18:08:22,561 INFO ThreadTest:60 Thread-4==> begin
2018-12-19 18:08:22,561 INFO ThreadTest:60 Thread-3==> begin
2018-12-19 18:08:22,568 INFO ThreadTest:46 begin:5
2018-12-19 18:08:22,604 INFO ThreadTest:54 end:5
2018-12-19 18:08:22,616 INFO ThreadTest:46 begin:6
2018-12-19 18:08:22,613 INFO ThreadTest:60 Thread-5==> begin
2018-12-19 18:08:22,623 INFO ThreadTest:60 Thread-6==> begin
2018-12-19 18:08:22,622 INFO ThreadTest:54 end:6
2018-12-19 18:08:22,639 INFO ThreadTest:46 begin:7
2018-12-19 18:08:22,643 INFO ThreadTest:54 end:7
2018-12-19 18:08:22,653 INFO ThreadTest:46 begin:8
2018-12-19 18:08:22,643 INFO ThreadTest:60 Thread-7==> begin
2018-12-19 18:08:22,657 INFO ThreadTest:60 Thread-8==> begin
2018-12-19 18:08:22,657 INFO ThreadTest:54 end:8
2018-12-19 18:08:22,672 INFO ThreadTest:46 begin:9
2018-12-19 18:08:22,678 INFO ThreadTest:54 end:9
2018-12-19 18:08:22,681 INFO ThreadTest:60 Thread-9==> begin
2018-12-19 18:08:23,521 INFO ThreadTest:63 Thread-1==>Thread-9
2018-12-19 18:08:23,526 INFO ThreadTest:63 Thread-0==>Thread-9
2018-12-19 18:08:23,536 INFO ThreadTest:63 Thread-2==>Thread-9
2018-12-19 18:08:23,574 INFO ThreadTest:63 Thread-4==>Thread-9
2018-12-19 18:08:23,588 INFO ThreadTest:63 Thread-3==>Thread-9
2018-12-19 18:08:23,628 INFO ThreadTest:63 Thread-5==>Thread-9
2018-12-19 18:08:23,634 INFO ThreadTest:63 Thread-6==>Thread-9
2018-12-19 18:08:23,666 INFO ThreadTest:63 Thread-7==>Thread-9
2018-12-19 18:08:23,668 INFO ThreadTest:63 Thread-8==>Thread-9
2018-12-19 18:08:23,697 INFO ThreadTest:63 Thread-9==>Thread-9
ThreadLocalMap 工具类
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ThreadLocalMap {
/**
* The constant threadContext.
*/
private final static ThreadLocal<Map<String, Object>> THREAD_CONTEXT = new MapThreadLocal();
/**
* Put.
*
* @param key the key
* @param value the value
*/
public static void put(String key, Object value) {
getContextMap().put(key, value);
}
/**
* Remove object.
*
* @param key the key
*
* @return the object
*/
public static Object remove(String key) {
return getContextMap().remove(key);
}
/**
* Get object.
*
* @param key the key
*
* @return the object
*/
public static Object get(String key) {
return getContextMap().get(key);
}
private static class MapThreadLocal extends ThreadLocal<Map<String, Object>> {
/**
* Initial value map.
*
* @return the map
*/
@Override
protected Map<String, Object> initialValue() {
return new HashMap<String, Object>(8) {
private static final long serialVersionUID = 3637958959138295593L;
@Override
public Object put(String key, Object value) {
return super.put(key, value);
}
};
}
}
/**
* 取得thread context Map的实例。
*
* @return thread context Map的实例
*/
private static Map<String, Object> getContextMap() {
return THREAD_CONTEXT.get();
}
/**
* 清理线程所有被hold住的对象。以便重用!
*/
public static void remove() {
getContextMap().clear();
}
}