ThreadLocal和hashmap对比测试线程安全

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();
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值