浅谈ThreadLocal模式
一、前言:
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模式的更多相关文章
- 浅谈MVVM模式和MVP模式——Vue.js向
浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...
- iOS:个人浅谈工厂模式
一.什么是工厂方法? 正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟到子类中进行.工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好 ...
- 浅谈pageobject模式
先来看两段代码 代码1: package com.zlshuo.selenium.nonaming.pageobject; /** * @author leshuo * @version 2014年5 ...
- 浅谈MVC模式
MVC模式(三层架构模式) (Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...
- 设计模式浅谈----策略模式(c#及java实现)
一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...
- 浅谈 ThreadLocal
有时,你希望将每个线程数据(如用户ID)与线程关联起来.尽管可以使用局部变量来完成此任务,但只能在本地变量存在时才这样做.也可以使用一个实例属性来保存这些数据,但是这样就必须处理线程同步问题.幸运的是 ...
- 浅谈MVC模式与MVVM模式的区别
MVC模式: M:Model(数据模型),用于存放数据 V:View(视图),也就是用户界面 C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给V ...
- Swift语言精要 - 浅谈代理模式(Delegate)
在iOS编程中,我们经常谈到代理代理,也就是delegate,那么什么是代理呢? 我们来看一下cocoa对它的描述: Delegation is Cocoa’s term for passing of ...
- 设计模式之——浅谈strategy模式(策略模式)
strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...
随机推荐
- 系列文章--Node.js学习笔记系列
Node.js学习笔记系列总索引 Nodejs学习笔记(一)--- 简介及安装Node.js开发环境 Nodejs学习笔记(二)--- 事件模块 Nodejs学习笔记(三)--- 模块 Nodejs学 ...
- poj 3469 Dual Core CPU——最小割
题目:http://poj.org/problem?id=3469 最小割裸题. 那个限制就是在 i.j 之间连双向边. 根据本题能引出网络流中二元关系的种种. 别忘了写 if ( x==n+1 ) ...
- Poj 2304 Combination Lock(模拟顺、逆时钟开组合锁)
一.题目大意 模拟一个开组合的密码锁过程.就像电影你开保险箱一样,左转几圈右转几圈的就搞定了.这个牌子的锁呢,也有它独特的转法.这个锁呢,有一个转盘,刻度为0~39.在正北方向上有一个刻度指针.它的密 ...
- Poj1258_Agri-Net(最小生成树)
一.Description(poj1258) Farmer John has been elected mayor of his town! One of his campaign promises ...
- Qt安装与配置
安装Qt 安装Qt Creator,打开终端执行如下命令: sudo apt-get install qt5-default qtcreator -y 安装Qt示例和文档: sudo apt-get ...
- 【转】Pro Android学习笔记(十二):了解Intent(下)
解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...
- openstackM版本安装
部署期间常见问题:http://www.cnblogs.com/bfmq/p/6001233.html,问题跟对架构的理解永远比部署重要!你玩技术是绝对是要基于理论的 一.基本情况:物理设备:4台惠普 ...
- TS学习之接口
TypeScript的核心原则之一是对值所具有的结构进行类型检查.接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约. interface testType { name: string; ...
- Eclipse调试Java程序技巧
主要步骤.Debug As"->"Java Application".双击设置断点,F5是跳进,F6是执行下一步,F7是跳出 在看这篇文章前,我推荐你看一下Ecli ...
- [51nod1101]换零钱
题意:给定钱,计算其能换成零钱的分类种数. 解题关键:完全背包计数. $dp[i][j]$表示前i个物品构成j元的种类数,然后优化一维. #include<bits/stdc++.h> u ...