- 浏览: 213241 次
- 性别:
- 来自: 北京
-
文章分类
引用自http://www.riabook.cn/doc/designpattern/ThreadSpecificStorage.htm
无论如何,要编写一个多执行绪安全(thread-safe)的程式总是困难的,为了使用的共用资源,您必须小心的对共用资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意物件的锁定与释放,避免产生死结,种种因素都使得编写多执行绪程式变得困难。
Thread-Specific Storage模式尝试从另一个角度来解释多执行绪共用资源的问题,其思考点很简单,即然共用资源这么困难,那么就干脆不要共用,何不为每个执行绪创造一个资源的复本,将每一个执行绪存取资料的行为加以隔离,其实现的方法,就是给予每一个执行绪一个特定空间来保管该执行绪所独享的资源,也因此而称之为 Thread- Specific Storage模式。
在Java中可以使用java.lang.ThreadLocal来实现这个模式,这个类别是从1.2之后开始提供,不过先来看看,如何自行实现一个简单的ThreadLocal类别:
ThreadLocal.java
import java.util.*;
public class ThreadLocal {
private Map storage = Collections.synchronizedMap(new HashMap());
public Object get() {
Thread current = Thread.currentThread();
Object o = storage.get(current);
if(o == null && !storage.containsKey(current)) {
o = initialValue();
storage.put(current, o);
}
return o;
}
public void set(Object o) {
storage.put(Thread.currentThread(), o);
}
public Object initialValue() {
return null;
}
}
可以看到程式中使用执行绪本身作为key值,并将所获得的资源放在Map物件中,如果第一次使用get(),也配置一个空间给执行绪,而 initialValue()可以用来设定什么样的初值要先储存在这个空间中,在这边先简单的设定为null。
现在假设有一个原先在单执行绪环境下的资源SomeResource,现在考虑要该其在多执行绪环境下使用,若不想考虑复杂的执行绪共用互斥问题,此时可以使用ThreadLocal类别来使用SomeResource,例如:
Resource.java
public class Resource {
private static final ThreadLocal threadLocal = new ThreadLocal();
public static SomeResource getResource() {
SomeResource resource = (SomeResource) threadLocal.get(); if(resource == null) {
resource = new SomeResource();
threadLocal.set(resource);
}
return resource;
}
}
上面所实作的ThreadLocal类别只是一个简单的示范,您可以使用java.lang.ThreadLocal来实现Thread- Specific Storage模式,以获得更好的效能,在这边简单的示范一个Log程式,它可以记录每个执行绪的活动,所使用的是 java.util.logging中的类别:
SimpleThreadLogger.java
import java.io.*;import java.util.logging.*; public class SimpleThreadLogger {
private static final ThreadLocal threadLocal = new ThreadLocal();
public static void log(String msg) {
getThreadLogger().log(Level.INFO, msg);
}
private static Logger getThreadLogger() {
Logger logger = (Logger) threadLocal.get();
if(logger == null) {
try {
logger = Logger.getLogger( Thread.currentThread().getName()); // Logger 预设是在主控台输出 // 我们加入一个档案输出的Handler // 它会输出XML的记录文件
logger.addHandler(
new FileHandler( Thread.currentThread().getName() + ".log"));
} catch(IOException e) {}
threadLocal.set(logger); }
return logger; }
}
可以使用下面这个程式来测试:
LoggerTest.java
public class LoggerTest {
public static void main(String[] args) {
new TestThread("thread1").start();
new TestThread("thread2").start();
new TestThread("thread3").start();
}}
class TestThread extends Thread {
public TestThread(String name) {
super(name);
}
public void run() {
for(int i = 0; i < 10; i++) {
SimpleThreadLogger.log(getName() + ": message " + i);
try { Thread.sleep(1000);
}
catch(Exception e) {
SimpleThreadLogger.log(e.toString());
}
}
}}
执行LoggerTest可以在主控台上看到输出,并可以在同一目录下找到三个log档,分别记录了三个执行绪的活动,透过 ThreadLocal,不用撰写复杂的执行绪共用互斥逻辑。
Thread-Specific Storage模式的意义之一,就是“有时不共用是好的”,如果共用会产生危险,那就不要共用,当然,这种方式所牺牲掉的就是空间,您必须为每一个执行绪保留它们独立的空间,这是一种以空间换取时间与安全性的方法。
无论如何,要编写一个多执行绪安全(thread-safe)的程式总是困难的,为了使用的共用资源,您必须小心的对共用资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意物件的锁定与释放,避免产生死结,种种因素都使得编写多执行绪程式变得困难。
Thread-Specific Storage模式尝试从另一个角度来解释多执行绪共用资源的问题,其思考点很简单,即然共用资源这么困难,那么就干脆不要共用,何不为每个执行绪创造一个资源的复本,将每一个执行绪存取资料的行为加以隔离,其实现的方法,就是给予每一个执行绪一个特定空间来保管该执行绪所独享的资源,也因此而称之为 Thread- Specific Storage模式。
在Java中可以使用java.lang.ThreadLocal来实现这个模式,这个类别是从1.2之后开始提供,不过先来看看,如何自行实现一个简单的ThreadLocal类别:
ThreadLocal.java
import java.util.*;
public class ThreadLocal {
private Map storage = Collections.synchronizedMap(new HashMap());
public Object get() {
Thread current = Thread.currentThread();
Object o = storage.get(current);
if(o == null && !storage.containsKey(current)) {
o = initialValue();
storage.put(current, o);
}
return o;
}
public void set(Object o) {
storage.put(Thread.currentThread(), o);
}
public Object initialValue() {
return null;
}
}
可以看到程式中使用执行绪本身作为key值,并将所获得的资源放在Map物件中,如果第一次使用get(),也配置一个空间给执行绪,而 initialValue()可以用来设定什么样的初值要先储存在这个空间中,在这边先简单的设定为null。
现在假设有一个原先在单执行绪环境下的资源SomeResource,现在考虑要该其在多执行绪环境下使用,若不想考虑复杂的执行绪共用互斥问题,此时可以使用ThreadLocal类别来使用SomeResource,例如:
Resource.java
public class Resource {
private static final ThreadLocal threadLocal = new ThreadLocal();
public static SomeResource getResource() {
SomeResource resource = (SomeResource) threadLocal.get(); if(resource == null) {
resource = new SomeResource();
threadLocal.set(resource);
}
return resource;
}
}
上面所实作的ThreadLocal类别只是一个简单的示范,您可以使用java.lang.ThreadLocal来实现Thread- Specific Storage模式,以获得更好的效能,在这边简单的示范一个Log程式,它可以记录每个执行绪的活动,所使用的是 java.util.logging中的类别:
SimpleThreadLogger.java
import java.io.*;import java.util.logging.*; public class SimpleThreadLogger {
private static final ThreadLocal threadLocal = new ThreadLocal();
public static void log(String msg) {
getThreadLogger().log(Level.INFO, msg);
}
private static Logger getThreadLogger() {
Logger logger = (Logger) threadLocal.get();
if(logger == null) {
try {
logger = Logger.getLogger( Thread.currentThread().getName()); // Logger 预设是在主控台输出 // 我们加入一个档案输出的Handler // 它会输出XML的记录文件
logger.addHandler(
new FileHandler( Thread.currentThread().getName() + ".log"));
} catch(IOException e) {}
threadLocal.set(logger); }
return logger; }
}
可以使用下面这个程式来测试:
LoggerTest.java
public class LoggerTest {
public static void main(String[] args) {
new TestThread("thread1").start();
new TestThread("thread2").start();
new TestThread("thread3").start();
}}
class TestThread extends Thread {
public TestThread(String name) {
super(name);
}
public void run() {
for(int i = 0; i < 10; i++) {
SimpleThreadLogger.log(getName() + ": message " + i);
try { Thread.sleep(1000);
}
catch(Exception e) {
SimpleThreadLogger.log(e.toString());
}
}
}}
执行LoggerTest可以在主控台上看到输出,并可以在同一目录下找到三个log档,分别记录了三个执行绪的活动,透过 ThreadLocal,不用撰写复杂的执行绪共用互斥逻辑。
Thread-Specific Storage模式的意义之一,就是“有时不共用是好的”,如果共用会产生危险,那就不要共用,当然,这种方式所牺牲掉的就是空间,您必须为每一个执行绪保留它们独立的空间,这是一种以空间换取时间与安全性的方法。
发表评论
-
多种单例模式的分析
2012-03-28 18:06 0blog.csdn.net/derpvailzhangfan/ ... -
JDK中的设计模式
2012-03-14 22:56 01.Abstract Factory •java.util.C ... -
简单工厂模式使用心得(使用场景)
2012-02-23 18:24 11499在实际项目中,简单工厂模式是我们使用的最多的设计模式之一,简单 ... -
AbstractList中Iterator模式的妙用
2012-01-13 11:51 954AbstractList中为了实现顺序访问AbstractLi ... -
适合使用命令模式的情景
2012-01-13 11:31 897情景1.当借个类都拥有 ... -
Iterator模式
2012-01-13 10:57 867我个人常叫它游标模式,该模式的主要目的就是,顺序访问集合中的各 ... -
使用工厂设计模式的场景
2012-01-12 15:43 2755创建类对象虽然可以使用new(底层也是通过反射创建对象的),但 ... -
JDK中使用的设计模式
2012-01-13 10:04 14261.抽象工厂模式 实 ... -
JDK中使用的设计模式代码实例
2012-01-05 17:38 0http://stackoverflow.com/questi ... -
享元模式
2011-12-23 10:22 1015通常情况下,我们会需 ... -
策略模式
2011-12-22 17:07 851所谓策略模式就是定义了多种算法,而让不同算法之间的切换不会影响 ... -
合成设计模式
2011-12-22 16:28 964如果要将对象组织到树中,使用树来表示对象之间的关系,请考虑使用 ... -
责任链模式
2011-12-20 18:35 813此文转正于http://wenku.baidu.com/vie ... -
桥梁设计模式
2011-12-19 18:19 821如果有很多对象要处理,而又有很多操作要做。这时可以考虑使用桥梁 ... -
代理模式
2011-11-30 15:26 914代理模式实际上是对对象的一种代理,以控制对象的访问。 有些情况 ... -
观察者模式
2011-11-16 14:48 1384声明转载的,简单易懂,呵呵 观察者模式的构造 l 抽 ... -
命令模式
2011-11-16 14:11 1232今天想学学命令模式,看见了一个文章讲的就是命令模式,感觉实例比 ... -
建造模式
2011-11-14 12:03 896建造模式是将负责对象 ... -
设计模式之适配器模式
2011-11-09 18:24 946适配器模式:主要是为了解决,老的对象在新的环境中不兼容的现象。 ... -
设计模式之模版方法
2011-11-09 16:31 794模版方法是一种非常简单的设计模式:简单的理解就是将关键的业务方 ...
相关推荐
Phase Termination——快把玩具收拾好,去睡觉吧 第11章 Thread-Specific Storage——每个线程的保管箱 第12章 Active Object——接受异步消息的主动对象 总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B...
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
vc++ 多线程教程---线程通信--利用事件对象,线程同步--使用信号量,线程同步--使用互斥量,线程同步--使用临界区
多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍Java线程相关的设计模式概念,并且通过实际的Java程序范例和 UML图示来一一解说,书中在代码的重要部分加上标注使读者更加容易...
Java多线程设计模式 清晰完整PDF版 Java多线程设计模式源代码
第11章 Thread-Specific Storage——每个线程的保管箱 第12章 Active Object——接受异步消息的主动对象 总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B Java的内存模型 附录C Java线程的优先级 附录D ...
图解java多线程设计模式-结城浩-完整高清带书签版本,原书扫描,高清,带有书签,希望大家喜欢
java多线程设计模式.pdf java多线程设计模式.pd
java多线程设计模式----------------------------------------------------
《Java多线程编程实战指南(设计模式篇)》采用Java(JDK1.6)语言和UML 为描述语言,并结合作者多年工作经历的相关实战案例,介绍了多线程环境下常用设计模式的来龙去脉:各个设计模式是什么样的及其典型的实际应用...
C++多线程一步步编程C++多线程一步步编程---多线程
模拟jdbc多线程竞争资源---【Eclipse项目】
Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点续传 Java多线程与线程安全实践-基于Http协议的断点...Java多线程与
Java多线程设计模式源代码
图解 java多线程设计模式 源码(自己写的)
javaweb毕业设计-Java多线程与线程安全实践-基于Http协议的断点续传(可做课程设计).rarjavaweb毕业设计-Java多线程与线程安全实践-基于Http协议的断点续传(可做课程设计).rarjavaweb毕业设计-Java多线程与线程安全...
Java多线程与线程安全实践-基于Http协议的断点续传Java多线程与线程安全实践-基于Http协议的断点续传Java多线程与线程安全实践-基于Http协议的断点续传Java多线程与线程安全实践-基于Http协议的断点续传Java多线程与...
基于Java多线程与线程安全实践-基于Http协议的断点续传设计与实现.zip基于Java多线程与线程安全实践-基于Http协议的断点续传设计与实现.zip基于Java多线程与线程安全实践-基于Http协议的断点续传设计与实现.zip基于...
最近收集的VB.Net-C#多线程Thread-代理委托delegate编程。文章列表: c#.net多线程同步.txt C#WebBrowser页面与WinForm交互技巧一.txt C#多线程编程-多细全.txt C#多线程编程简单实例.txt C#多线程窗体控件安全访问....