首先来看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模式的核心元素的更多相关文章

  1. Struts2中的设计模式----ThreadLocal模式

    http://www.cnblogs.com/gw811/archive/2012/09/07/2675105.html 设计模式(Design pattern):是经过程序员反复实践后形成的一套代码 ...

  2. 【转】Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式

    [转]Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式 博客分类: 企业应用面临的问题 java并发编程 Struts2的线程安全ThreadLocal模式St ...

  3. 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】

    一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: ...

  4. HTML核心元素

    一 HTML核心元素 1.文本标题 <h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标题</h3> ... ...

  5. 【深入比较ThreadLocal模式与synchronized关键字】

    [深入比较ThreadLocal模式与synchronized关键字]ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题.只是两者处理问题的角度和思路不同. ...

  6. ThreadLocal模式探索

    一.首先,ThreadLocal模式使共享数据能多个线程被访问,每个线程访问的只是这个数据的副本,线程之间互不影响. 例子1: package Thread2; public class Counte ...

  7. ThreadLocal模式的原理

    在JDK的早期版本中,提供了一种解决多线程并发问题的方案:java.lang.ThreadLocal类.ThreadLocal类在维护变量时,实际使用了当前线程(Thread)中的一个叫做Thread ...

  8. 【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 ...

  9. ThreadLocal模式与synchronized关键字的比较

    ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题.只是两者处理问题的角度和思路不同. 1)ThreadLocal是一个Java类,通过对当前线程(Thre ...

随机推荐

  1. SSIS ETL BEST PRACTICE

    PackageRunLog(ExecutionGuid,PackageName,SourceTableName,DestinationTableName,StartTimeUTC,EndTimeUTC ...

  2. 循环 wxl

    #include <cstdio> #include <cstring> #include <string> #include <algorithm> ...

  3. [转]MySQL数据库的优化-运维架构师必会高薪技能,笔者近六年来一线城市工作实战经验

    本文转自:http://liangweilinux.blog.51cto.com/8340258/1728131 年,嘿,废话不多说,下面开启MySQL优化之旅! 我们究竟应该如何对MySQL数据库进 ...

  4. HDU 5029 Relief grain --树链剖分第一题

    题意:给一棵树,每次给两个节点间的所有节点发放第k种东西,问最后每个节点拿到的最多的东西是哪种. 解法:解决树的路径上的修改查询问题一般用到的是树链剖分+线段树,以前不会写,后来学了一下树链剖分,感觉 ...

  5. Android系列----JUnit单元测试的使用

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  6. 关于eclipse入门开发c/c++文章推荐

    1. 关于编译说明. http://www.ibm.com/developerworks/cn/linux/opensource/os-ecc/ 2. 关于快捷键与代码阅读 http://www.cn ...

  7. [原创]CI持续集成系统环境---部署Jenkins完整记录

    Jenkins通过脚本任务触发,实现代码的自动化分发,是CI持续化集成环境中不可缺少的一个环节. 下面对Jenkins环境的部署做一记录. ------------------------------ ...

  8. action中result没有值

    action中result没有值,访问action会输出action中的所有数据,输出类型为.action类型 .

  9. Spring小练习之宝宝淘项目

    数据库准备 # 表结构 CREATE TABLE `t01_user` ( `) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `) DEFAULT NULL COM ...

  10. [2]Telerik Extensions for ASP.NET MVC 中文教程(2)

    上一篇文章对Telerik MVC Extensions作了一个大概的介绍,这篇文章将介绍如何将Telerik MVC Extensions添加到项目中.有以下两种方式可以将Telerik MVC E ...