加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

正确理解Thread Local的原理与适用场景

发布时间:2018-08-17 01:49:25 所属栏目:教程 来源:郭俊
导读:技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战 一、ThreadLocal解决什么问题 由于 ThreadLocal 支持范型,如 ThreadLocal StringBuilder ,为表述方便,后文用 变量 代表 ThreadLocal 本身,而用 实例 代表具体类型(如 StringBui
副标题[/!--empirenews.page--] 技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战

一、ThreadLocal解决什么问题

由于 ThreadLocal 支持范型,如 ThreadLocal< StringBuilder >,为表述方便,后文用 变量 代表 ThreadLocal 本身,而用 实例 代表具体类型(如 StringBuidler )的实例。

1. 不恰当的理解

写这篇文章的一个原因在于,网上很多博客关于 ThreadLocal 的适用场景以及解决的问题,描述的并不清楚,甚至是错的。下面是常见的对于 ThreadLocal的介绍

  • ThreadLocal为解决多线程程序的并发问题提供了一种新的思路
  • ThreadLocal的目的是为了解决多线程访问资源时的共享问题

还有很多文章在对比 ThreadLocal 与 synchronize 的异同。既然是作比较,那应该是认为这两者解决相同或类似的问题。

上面的描述,问题在于,ThreadLocal 并不解决多线程 共享 变量的问题。既然变量不共享,那就更谈不上同步的问题。

2. 合理的理解

ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String 类型变量),在不同的 Thread 中有不同的副本(实际是不同的实例,后文会详细阐述)。这里有几点需要注意

  • 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来
  • 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题
  • 既无共享,何来同步问题,又何来解决同步问题一说?

那 ThreadLocal 到底解决了什么问题,又适用于什么样的场景?

核心意思是

总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。后文会通过实例详细阐述该观点。另外,该场景下,并非必须使用 ThreadLocal ,其它方式完全可以实现同样的效果,只是 ThreadLocal 使得实现更简洁。

二、ThreadLocal用法

1. 实例代码

下面通过如下代码说明 ThreadLocal 的使用方式

  1. public class ThreadLocalDemo { 
  2.   public static void main(String[] args) throws InterruptedException { 
  3.     int threads = 3; 
  4.     CountDownLatch countDownLatch = new CountDownLatch(threads); 
  5.     InnerClass innerClass = new InnerClass(); 
  6.     for(int i = 1; i <= threads; i++) { 
  7.       new Thread(() -> { 
  8.         for(int j = 0; j < 4; j++) { 
  9.           innerClass.add(String.valueOf(j)); 
  10.           innerClass.print(); 
  11.         } 
  12.         innerClass.set("hello world"); 
  13.         countDownLatch.countDown(); 
  14.       }, "thread - " + i).start(); 
  15.     } 
  16.     countDownLatch.await(); 
  17.   } 
  18.   private static class InnerClass { 
  19.     public void add(String newStr) { 
  20.       StringBuilder str = Counter.counter.get(); 
  21.       Counter.counter.set(str.append(newStr)); 
  22.     } 
  23.     public void print() { 
  24.       System.out.printf("Thread name:%s , ThreadLocal hashcode:%s, Instance hashcode:%s, Value:%sn", 
  25.       Thread.currentThread().getName(), 
  26.       Counter.counter.hashCode(), 
  27.       Counter.counter.get().hashCode(), 
  28.       Counter.counter.get().toString()); 
  29.     } 
  30.     public void set(String words) { 
  31.       Counter.counter.set(new StringBuilder(words)); 
  32.       System.out.printf("Set, Thread name:%s , ThreadLocal hashcode:%s,  Instance hashcode:%s, Value:%sn", 
  33.       Thread.currentThread().getName(), 
  34.       Counter.counter.hashCode(), 
  35.       Counter.counter.get().hashCode(), 
  36.       Counter.counter.get().toString()); 
  37.     } 
  38.   } 
  39.   private static class Counter { 
  40.     private static ThreadLocal<StringBuilder> counter = new ThreadLocal<StringBuilder>() { 
  41.       @Override 
  42.       protected StringBuilder initialValue() { 
  43.         return new StringBuilder(); 
  44.       } 
  45.     }; 
  46.   } 

2. 实例分析

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读