zoukankan      html  css  js  c++  java
  • Java并发编程之ThreadLocal类

    ThreadLocal类可以理解为ThreadLocalVariable(线程局部变量)提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程在调用set时设置的最新值。可以将ThreadLocal<T>视为 包含了Map<Thread,T>对象,保存了特定于该线程的值。

    概括起来说,对于多线程资源共享的问题,同步机制采用了以时间换空间的方式,而ThreadLocal采用了以空间换时间的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

    模拟ThreadLocal

      import java.util.Collections;
      import java.util.HashMap;
      import java.util.Map;
       
      public class SimpleThreadLocal<T> {
      private Map<Thread, T> valueMap = Collections
      .synchronizedMap(new HashMap<Thread, T>());
       
      public void set(T newValue) {
      valueMap.put(Thread.currentThread(), newValue); // ①键为线程对象,值为本线程的变量副本
      }
       
      public T get() {
      Thread currentThread = Thread.currentThread();
      T o = valueMap.get(currentThread); // ②返回本线程对应的变量
      if (o == null && !valueMap.containsKey(currentThread)) { // ③如果在Map中不存在,放到Map中保存起来。
      o = initialValue();
      valueMap.put(currentThread, o);
      }
      return o;
      }
       
      public void remove() {
      valueMap.remove(Thread.currentThread());
      }
       
      protected T initialValue() {
      return null;
      }
      }
    实用ThreadLocal

      class Count {
      private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
      @Override
      protected Integer initialValue() {
      return 0;
      }
      };
       
      public Integer increase() {
      count.set(count.get() + 1);
      return count.get();
      }
       
      }
       
      class TestThread implements Runnable {
      private Count count;
       
      public TestThread(Count count) {
      this.count = count;
      }
       
      @Override
      public void run() {
      // TODO Auto-generated method stub
      for (int i = 1; i <= 3; i++) {
      System.out.println(Thread.currentThread().getName() + " " + i
      + "th " + count.increase());
      }
      }
      }
       
      public class TestThreadLocal {
      public static void main(String[] args) {
      Count count = new Count();
      Thread t1 = new Thread(new TestThread(count));
      Thread t2 = new Thread(new TestThread(count));
      Thread t3 = new Thread(new TestThread(count));
      Thread t4 = new Thread(new TestThread(count));
      t1.start();
      t2.start();
      t3.start();
      t4.start();
      }
      }

    输出
    Thread-0    1th    1
    Thread-0    2th    2
    Thread-0    3th    3
    Thread-3    1th    1
    Thread-1    1th    1
    Thread-1    2th    2
    Thread-2    1th    1
    Thread-1    3th    3
    Thread-3    2th    2
    Thread-3    3th    3
    Thread-2    2th    2
    Thread-2    3th    3  




  • 相关阅读:
    Vue 封装axios(四种请求)及相关介绍
    简单的按钮样式,两个连在一起的按钮
    http接口访问正常,https访问报错,基础连接已经关闭: 发送时发生错误.
    单点登录思路,多台服务器共用一个数据库,登录信息解决方案
    Wait()在过滤器中卡住 ,在异步代码上阻塞时的常见死锁问题
    接口对接,接口通过原有代码无法访问,解决办法,用postman解决
    svg基础标签说明
    server 2016部署网络负载平衡(NLB)
    写 JS 逻辑判断,不要只知道用 if-else 和 switch
    .NetCore部署IIS出错原因未安装ASP.N.NetCore部署IIS出错原因未安装ASP.NET Core Module v2ET Core Module v2
  • 原文地址:https://www.cnblogs.com/csu_xajy/p/4342724.html
Copyright © 2011-2022 走看看