一、前言:

  ThreadLocal模式,严格意义上不是一种设计模式,而是java中解决多线程数据共享问题的一个方案。ThreadLocal类是java JDK中提供的一个类,用来解决线程安全问题,并不是线程类。

二、基础:

  线程安全:简单来说,指的是在多线程环境中,对类的内部实例变量的访问是安全的。而方法声明中的参数变量以及方法中的内部变量是不存在线程安全问题,因为每个线程独自管理自己方法内部的变量。

三、原理与实现:

  1,原理:多个线程访问同一共享变量时,ThreadLocal类为每个线程提供一份该变量的副本,各个线程拥有一份属于自己的变量副本,操作修改的是各自的变量副本,而不会相互影响。

  2,看看JDK源码实现,你就会豁然开朗:

(1)Thread类中有一个变量threadLocals,意味着:每个线程有一个自己的变量,这个变量不会给别的线程操作访问,对吧?那么,我们把共享变量的副本,存储在这个变量中,这样就安全了吧?

/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

(2)接下来,看看ThreadLocal类是怎么操作这个变量的:

//把value保存在当前线程的本地变量中
  public void set(T value) {
Thread t = Thread.currentThread();
     //得到当前线程的本地变量 
ThreadLocalMap map = getMap(t);
if (map != null)
       //以当前的ThreadLocal实例作为Key,把值设进去
map.set(this, value);
else
createMap(t, value);
}
//提取当前线程中以ThreadLocal实例为Key的变量值
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
       //以当前的ThreadLocal实例作为Key
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
  private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
  ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
  public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
  static class ThreadLocalMap {.....}

你有没有看到,多个共享变量,怎么保存在线程的ThreadLocalMap中?以map的形式,那么key是什么?key就是ThreadLocal实例。有多个共享变量的时候,就会创建多个ThreadLocal实例与其对应,同一个线程中,各个共享变量就不会相互干扰。而线程与线程之间,更不会有干扰,每个线程访问的都是自己的ThreadLocalMap。

四、模式的使用:

  (1)使用场景:在同一个线程的不同开发层次中共享数据。如web应用开发中表示层、业务层、持久层需要共享数据;

  (2)使用步骤:

    1)建立一个类,在其中添加一个静态的ThreadLocal变量,使其成为一个共享环境;

    2)添加访问静态ThreadLocal的静态方法(设值和取值);

  (3)下面给出一个示例:

public class Counter {

    public static ThreadLocal<Integer> count = new ThreadLocal<Integer>(){
//通过匿名内部类覆盖ThreadLocal的InitialValue方法,指定初值
protected Integer initialValue() {
return 0;
};
}; //封装业务处理,操作储存于ThreadLocal中的变量
public static Integer getNext(){
count.set(count.get()+1);
return count.get();
} public static Integer get(){
return count.get();
} public static void set(Integer value){
count.set(value);
}
}
public class ThreadLocalTest {

    public class TestThread extends Thread{

        public void run() {
for(int i=0; i<10;i++){
System.out.println(Thread.currentThread()+" : "+Counter.getNext());
}
System.out.println("--------");
}
} public static void main(String[] args) throws InterruptedException {
ThreadLocalTest tt = new ThreadLocalTest(); Thread t1 = tt.new TestThread();
Thread t2 = tt.new TestThread();
Thread t3 = tt.new TestThread();
t1.start();
t2.start();
t3.start();
}
}

以上若有不当之前,欢迎拍砖。

浅谈ThreadLocal模式的更多相关文章

  1. 浅谈MVVM模式和MVP模式——Vue.js向

    浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...

  2. iOS:个人浅谈工厂模式

    一.什么是工厂方法? 正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟到子类中进行.工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好 ...

  3. 浅谈pageobject模式

    先来看两段代码 代码1: package com.zlshuo.selenium.nonaming.pageobject; /** * @author leshuo * @version 2014年5 ...

  4. 浅谈MVC模式

    MVC模式(三层架构模式) (Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  5. 设计模式浅谈----策略模式(c#及java实现)

    一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...

  6. 浅谈 ThreadLocal

    有时,你希望将每个线程数据(如用户ID)与线程关联起来.尽管可以使用局部变量来完成此任务,但只能在本地变量存在时才这样做.也可以使用一个实例属性来保存这些数据,但是这样就必须处理线程同步问题.幸运的是 ...

  7. 浅谈MVC模式与MVVM模式的区别

    MVC模式: M:Model(数据模型),用于存放数据 V:View(视图),也就是用户界面 C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给V ...

  8. Swift语言精要 - 浅谈代理模式(Delegate)

    在iOS编程中,我们经常谈到代理代理,也就是delegate,那么什么是代理呢? 我们来看一下cocoa对它的描述: Delegation is Cocoa’s term for passing of ...

  9. 设计模式之——浅谈strategy模式(策略模式)

    strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...

随机推荐

  1. 【C/C++】assert

    摘自http://www.cplusplus.com assert : macro #include <assert.h> void assert (int expression); 如果 ...

  2. 随机数 while循环 do while循环 for循环

    1.随机数   arc4random()    返回一个随机数 如果要随机[a,b]范围内的随机数   arc4random() % (b - a + 1) +  a ; 2.break  跳出本次循 ...

  3. NET Remoting 最简单示例

    NET Remoting 最简单示例 2014-01-21 15:29 10492人阅读 评论(4) 收藏 举报  分类: .NET(6)  版权声明:本文为博主原创文章,未经博主允许不得转载. 学习 ...

  4. C#自定义控件 ————进度条

    先看看样式 一个扇形的进度条 对外公开的方法和属性 事件 value_change;//值改变时触发的事件progress_finshed;//进度条跑完时触发的事件 属性 Max_value//获取 ...

  5. linux日常管理-vmstat命令

    系统负载用w查看.是什么原因造成了系统负载.查看系统负载状态 命令:vmstat vmstat就查看一次 vmstat 1 每秒钟更新一次.按ctrl+c取消. vmstat 1 5 每秒钟更新一次, ...

  6. web安全之同源策略

    为什么使用同源策略?一个重要原因就是对cookie的保护,cookie 中存着sessionID .如果已经登录网站,同时又去了任意其他网站,该网站有恶意JS代码.如果没有同源策略,那么这个网站就能通 ...

  7. CSS是什么?W3C是什么?W3C盒子与IE盒子的区别?

    (1)层叠样式(Cascading Style Sheets, CSS)是用来表现HTML或XML文本样式的语言.   (2)W3C推荐规范(World Wide Web Consortium,W3C ...

  8. 关于使用struts2跳转后css和js失效的解决方式

    根据观察,主要是由于通过action跳转后的url会根据命名空间,自动跳转到命名空间子目录,使得当前引用的css和js查找不到,从而失效,根据这个原因,可使用四种办法解决: 1.使用struts2.x ...

  9. p2921 Trick or Treat on the Farm

    传送门 题目 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N个牛棚里转 悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果.农场不大,所以约翰要想尽法子让奶牛们得到快乐 ...

  10. Struts2 资源配置文件国际化

    Struts2 资源配置文件国际化 Struts2资源文件的命名规范:basename_language_country.properties Struts2国际化如果系统同时存在资源文件.类文件,系 ...