浅谈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 ...
随机推荐
- BZOJ2212:[POI2011]Tree Rotation
浅谈线段树合并:https://www.cnblogs.com/AKMer/p/10251001.html 题目传送门:https://lydsy.com/JudgeOnline/problem.ph ...
- 块级&行内元素总结
一.块级元素与行内元素的区别 块级元素与行内元素有几个关键区别: 格式 默认情况下: 块级元素会新起一行: 行内元素不会以新行开始. 内容模型 一般块级元素可以包含行内元素和其他块级元素.这种结构上的 ...
- Ubuntu下安装软件
在ubuntu当中,安装应用程序有三种方法,分别是:apt-get,dpkg安装deb和make install安装源码包三种. apt-get方法 使用apt-get install来安装应用程序算 ...
- Python脚本开头两行:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用
转于:https://www.crifan.com/python_head_meaning_for_usr_bin_python_coding_utf-8/ 出处:在路上 一.基本功能 1)#!/us ...
- Python:map()、reduce()、filter()的区别
文章转于:https://blog.csdn.net/goupper1991/article/details/49803355 原文博主:https://blog.csdn.net/goupper19 ...
- unittest ,ddt数据驱动,读取文件中数据,多个参数时的处理
1. test.yaml中的数据 这里的属性是list 2.创建用例 3,在yaml中创建数据,创建list数据,list中再创建dict数据,这样就可以读取dict中的多个参数的数据了
- PHP7三元运算符 ?? 和 ?: 的区别
1. (expr1) ?? (expr2) 是 PHP7才有的功能,等同于: isset(expr1) ? expr1 : expr2 ; 2.(expr1) ?: (expr2) 是PHP5.3才 ...
- 关于 sklearn.decomposition.KernelPCA的简单介绍
from sklearn import decomposition import numpy as np A1_mean = [1, 1] A1_cov = [[2, .99], [1, 1]] A1 ...
- Wannafly 锁
题意: 现在有 $n$ 个人,每个人有一个已然给定的重要度 $a_i$,现有 K 个锁,每个锁有若干钥匙,分配给一些人,要求一群人能够打开全部 $K$ 把锁, 当且仅当他们重要度的和大于等于 $m$, ...
- C++中对象的常引用
直接传递对象名 用对象名做函数参数时,在函数调用时将建立一个新的对象,它是形参对象的拷贝. ================下面给出一个直接传递对象名的例子程序1.1================= ...