ThreadLocal模式的核心元素
首先来看ThreadLocal模式的实现机理:
在JDK的早期版本中,提供了一种解决多线程并发问题的方案:java.lang.ThreadLocal类。ThreadLocal类在维护变量时,世纪使用了当前线程(Thread)的一个叫做ThreadLocalMap的独立副本,每个线程可以独立修改属于自己的副本而不会互相影响,从而隔离了线程和线程,避免了线程访问实例变量发生冲突的问题。
ThreadLocal本身并不是一个线程而是通过操作当前线程中的一个内部变量来达到与其他线程隔离的目的。
ThreadLocal模式至少从两个方面完成了数据访问隔离,即横向隔离和纵向隔离,有了横向隔离和纵向两种不同的隔离方式,ThreadLocal模式就能真正的做到线程安全:
纵向隔离:线程与线程之间的数据访问隔离。这一点由线程的数据结构保证。因为每个线程都在进行对象访问时,访问的都是各个线程自己的ThreadLocalMap
横向隔离:同一个线程中,不同的ThreadLocal实例操作的对象之间相互隔离,这一点由ThreadLocalMap在存储时采用当前ThradLocal的实例作为key来保证。
深入比较ThreadLocal模式与synchronized关键字:
ThreadLocal模式与synchronized关键字都用于处理多线程并发访问变量的问题,只是二者处理问题的角度和思路不同。
1)ThreadLocal是一个Java类,通过对当前线程中的局部变量的操作来解决不同线程的变量访问的冲突问题。所以,ThreadLocal提供了线程安全的共享对象机制,每个线程都拥有其副本。
2)Java中的synchronized是一个保留字,它依靠JVM的锁机制来实现临界区的函数或者变量在访问中的原子性。在同步机制中。通过对象的锁机制保证同一时间只有一个线程访问变量。此时,被用作“锁机制”的变量是多个线程共享的。
同步机制(synchronized关键字)采用了“以时间换空间”的方式,提供一份变量,让不同的线程排队访问。而ThreadLocal采用了“以空间换时间”的方式,为每一个线程都提供一份变量的副本,从而实现同时访问而互不影响。
使用ThreadLocal模式的步骤:
1)建立一个雷,并在其中封装一个静态的ThreadLocal变量,使其成为一个共享数据环境。
2)在类中实现访问静态ThreadLocal变量的静态方法(设值和取值)
要完成ThreadLocal模式其中最关键的就是创建一个任何地方都可以访问到的ThreadLocal实例,我们通过类的静态实例变量来实现这个用于承载静态实例变量的类就被视作一个共享环境
例子:
package com.slp.ThreadLocal; public class Counter { /**
* 新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象
*/
private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>() {
protected synchronized Integer initialValue() {
return 10;
}
}; /**
* 通过静态的get方法访问ThreadLocal中存储的值
*
* @return
*/
public static Integer get() {
return counterContext.get();
} /**
* 通过静态的set方法将变量值设置到ThreadLocal中
*
* @param value
*/
public static void set(Integer value) {
counterContext.set(value);
} /**
* 封装业务逻辑,操作存储于ThreadLocal中的变量
*/
public static Integer getNextCounter() {
counterContext.set(counterContext.get() + 1);
return counterContext.get();
} }
这个类中,我们实现了一个静态的ThreadLocal变量,并通过get方法将ThreadLocal中存储的值暴漏处理,还封装了一个带有业务逻辑的方法getNextCounter,操作ThreadLocal中的值将其加1,并返回计算后的值。
这时这个Counter类就变成了一个数据共享环境,我们也拥有了实现ThreadLocal模式的关键要素。
package com.slp.ThreadLocal; public class ThreadLocalTest extends Thread {
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("Thread[" + Thread.currentThread().getName()
+ "],counter=" + Counter.getNextCounter());
}
} }
这是一个简单的线程类,循环输出当前线程的名称和getNextCounter的结果,由于getNextCounter中的逻辑所曹组的是ThreadLocal中的变量,也就是说,在同一个线程中,变量值会被连续累加。
package com.slp.ThreadLocal; public class Test { public static void main(String[] args) {
// TODO Auto-generated method stub ThreadLocalTest testThrad1 = new ThreadLocalTest();
ThreadLocalTest testThrad2 = new ThreadLocalTest();
ThreadLocalTest testThrad3 = new ThreadLocalTest();
testThrad1.start();
testThrad2.start();
testThrad3.start(); } }
执行结果:
Thread[Thread-2],counter=11
Thread[Thread-2],counter=12
Thread[Thread-2],counter=13
Thread[Thread-1],counter=11
Thread[Thread-0],counter=11
Thread[Thread-0],counter=12
Thread[Thread-0],counter=13
Thread[Thread-1],counter=12
Thread[Thread-1],counter=13
由此可以看出这个访问是线程安全的。
ThreadLocal模式最合适的使用场景:在同一个线程的不同开发层次中共享数据、
实现ThreadLocal模式的两个主要步骤:
1.建立一个类,并在其中封装一个静态的ThreadLocal变量使其成为一个共享的数据环境
2.在类中实现访问静态ThreadLocal变量的静态方法(设置和取值)
ThreadLocal模式的核心元素的更多相关文章
- Struts2中的设计模式----ThreadLocal模式
http://www.cnblogs.com/gw811/archive/2012/09/07/2675105.html 设计模式(Design pattern):是经过程序员反复实践后形成的一套代码 ...
- 【转】Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式
[转]Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式 博客分类: 企业应用面临的问题 java并发编程 Struts2的线程安全ThreadLocal模式St ...
- 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】
一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: ...
- HTML核心元素
一 HTML核心元素 1.文本标题 <h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标题</h3> ... ...
- 【深入比较ThreadLocal模式与synchronized关键字】
[深入比较ThreadLocal模式与synchronized关键字]ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题.只是两者处理问题的角度和思路不同. ...
- ThreadLocal模式探索
一.首先,ThreadLocal模式使共享数据能多个线程被访问,每个线程访问的只是这个数据的副本,线程之间互不影响. 例子1: package Thread2; public class Counte ...
- ThreadLocal模式的原理
在JDK的早期版本中,提供了一种解决多线程并发问题的方案:java.lang.ThreadLocal类.ThreadLocal类在维护变量时,实际使用了当前线程(Thread)中的一个叫做Thread ...
- 【UML】NO.54.EBook.6.UML.2.002-【Thinking In UML 大象 第二版】- UML 核心元素
1.0.0 Summary Tittle:[UML]NO.54.EBook.6.UML.2.002-[Thinking In UML 大象 第二版]- UML 核心元素 Style:DesignPat ...
- ThreadLocal模式与synchronized关键字的比较
ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题.只是两者处理问题的角度和思路不同. 1)ThreadLocal是一个Java类,通过对当前线程(Thre ...
随机推荐
- jQuery 1.9 .live() is not a function
jquery中的live()方法在jquery1.9及以上的版本中已被废弃了,如果使用,会抛出TypeError: $(...).live is not a function错误. 解决方法: 之前的 ...
- Java基础の乱弹琴二:break关键字
Java中的break一般用于 跳出一个switch或者循环. 跳出switch基本不用赘述. break跳出循环一般是跳出当前一层循环. 如若需要跳出多层循环可以在break后加标签,然后把标签标注 ...
- Intent详解
ntent组件虽然不是四大组件,但却是连接四大组件的桥梁,学习好这个知识,也非常的重要. 一.什么是Intent 1.Intent的概念: Android中提供了Intent机制来协助应用间的交互与通 ...
- struts2 基本用法
Struts2必需库: commons-fileupload.jar.commons-io-1.3.2.jar.freemarker-2.3.16.jar.javassist-3.7.ga.jar.o ...
- SSH 无密码访问其它机器 和 Windows 上 putty 无密码访问 Linux 机器
1. 从一台 Linux 机器(ubuntu1)上无密码访问其它机器(ubuntu2) (1)登录 ubuntu1 并切换到用户比如 s1 (2)运行 ssh-keygen -t rsa (3)运行c ...
- sqlite查询结果在listview中展示
1.获取db实例 SQLiteDatabase db=dbhelper.getWritableDatabase(); 2.Cursord对象获取查询结构 Cursor cursor=db.rawQue ...
- 《TCP/IP详解 卷一》读书笔记-----广播&多播&IGMP
1.广播和多播都只适用于UDP,因为TCP是面向连接的,需要将两台主机的两个进程绑定在一起,即IP地址和端口对 2.通常,网卡能看到网络中的每一个数据帧,但是往往它只接受目的地址与自己MAC地址相同的 ...
- 转载:HttpClient使用详解
原文地址:http://blog.csdn.net/wangpeng047/article/details/19624529 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自 ...
- 【Ext.Net学习笔记】03:Ext.Net DirectEvents用法详解、DirectMethods用法详解
Ext.Net通过DirectEvents进行服务器端异步的事件处理.[Ext.Net学习笔记]02:Ext.Net用法概览.Ext.Net MessageBus用法.Ext.Net布局 中已经简单的 ...
- 分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线
2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MB Description Alice和Bob现在要乘飞机旅行,他们选择了一家相 ...