一、前言:

  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. XML的二十个热点问题

    这些日子,几乎每个人都在谈论XML (Extensible Markup Language),但是很少有人真正理解其含义.XML的推崇者认为它能够解决所有HTML不能解决的问题,让数据在不同的操作系统 ...

  2. 安装DCOS,关于docker异常引发的调查

    入门DCOS,刚开始安装,碰到了一个异常: Bind for 0.0.0.0:9000 failed: port is already allocated. 调试这个问题花费了好长时间,因为无法通过n ...

  3. DataGrid 支持字符截断显示

    DataGrid支持截断时, 需要分2部分, DataGridColumnHeader和DataGridCell. 1)创建上述2部分的ControlTemplate . 2)把其中的ContentP ...

  4. su - user解释

    su [-fmp] [-c command] [-s shell] [--help] [--version] [-] [USER [ARG]] -c command:变更账号为USER的使用者,并执行 ...

  5. mysql du-master配置

    db-server1 my.cnf log_bin = mysql-binbinlog_format = mixedserver_id = 1 read-only = 0#binlog-do-db = ...

  6. 实用的原生js图片轮播

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. java--序列化及其算法透析

    有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍. Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述 ...

  8. Math(2)

    Math(2) public static void main(String[] args) { System.out.println(Math.floor(-32.8)); //常数 System. ...

  9. Zabbix_proxy的架设

    一.安装zabbix-proxy与导入数据库 1. 安装 zabbix-server $ sudo rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/7/ ...

  10. 关于android 数据库查询出现 _id column do not exist 的处理

    查询的字段必须带上_id字段,否则就会出现此类异常,导致程序崩溃