Java多线程 - ThreadLocal类的使用

  • ThreadLocal是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问

    • 他内部储存的是一个键值对Map,其中key是某个线程,value就是这个线程自己set的值,所以对于一个线程来说,一个ThreadLocal只能存一个值

    • ThreadLocal支持泛型,也就是支持value是可以设置类型的,像是ThreadLocal<Date>就是设置value为Date类型

  • ThreadLocal常用的方法

    • set(x) : 设置此线程的想要放的值是多少

    • get() : 取得此线程当初存放的值,如果没有存放过则返回null

    • remove() : 删除此线程的键值对,也就是如果先执行remove再执行get,会返回null

  • ThreadLocal通常用在SimpleDateFormat,或是SpringMVC上

    • 因为SimpleDateFormat不是线程安全的,因此虽然可以每次要使用的时候重新new一个,但是这样做会很浪费资源,所以如果使用ThreadLocal在每个线程裡都存放一个此线程专用的SimpleDateFormat,就可以避免一直new的资源浪费,又确保线程安全

    • 因为SpringMVC会对每个请求分配一个线程,可以在拦截器将此线程的用户信息(ip、名字...)使用ThreadLocal储存,这样在后续要用到用户信息的地方时,就可以去ThreadLocal中取得,而且因为ThreadLocal可以隔离线程,因此每条请求对应的线程的用户信息不会互相干扰

  • 具体实例

    • 每个线程都可以在ThreadLocal中放自己的值,且不会干扰到其他线程的值

      class Tools {
          public static ThreadLocal threadLocal = new ThreadLocal();
      }
      
      class MyThread extends Thread {
          @Override
          public void run() {
              if (Tools.threadLocal.get() == null) {
                  Tools.threadLocal.set(Thread.currentThread().getName() + ", " + Math.random());
              }
              System.out.println(Tools.threadLocal.get());
          }
      }
      
      public class Main {
          public static void main(String[] args) {
              for (int i = 0; i < 5; i++) {
                  MyThread thread = new MyThread();
                  thread.setName("thread " + i);
                  thread.start();
              }
          }
      }
      thread 1, 0.86
      thread 0, 0.42
      thread 2, 0.35
      thread 3, 0.41
      thread 4, 0.45
    • 使用ThreadLocal在SimpleDateFormat上,并且给ThreadLocal加上泛型,指定value的类型是SimpleDateFormat

      • 因为使用了ThreadLocal确保每个线程有自己一份SimpleDateFormat,所以线程安全,不会报错

      class Tools {
          public static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
      }
      
      class MyThread extends Thread {
          @Override
          public void run() {
              SimpleDateFormat sdf = Tools.threadLocal.get();
              if (sdf == null) {
                  sdf = new SimpleDateFormat("yyyy-MM-dd");
                  Tools.threadLocal.set(sdf);
              }
              try {
                  System.out.println(sdf.parse("2018-07-15"));
              } catch (ParseException e) {
                  System.out.println("报错了");
              }
          }
      }
      
      public class Main {
          public static void main(String[] args) {
              for (int i = 0; i < 5; i++) {
                  MyThread thread = new MyThread();
                  thread.setName("thread " + i);
                  thread.start();
              }
          }
      }
      Sun Jul 15 00:00:00 CST 2018
      Sun Jul 15 00:00:00 CST 2018
      Sun Jul 15 00:00:00 CST 2018
      Sun Jul 15 00:00:00 CST 2018
      Sun Jul 15 00:00:00 CST 2018

猜你喜欢

转载自blog.csdn.net/weixin_40341116/article/details/81060893