`

多线程设计模式(Thread-Specific storage)

阅读更多
引用自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模式的意义之一,就是“有时不共用是好的”,如果共用会产生危险,那就不要共用,当然,这种方式所牺牲掉的就是空间,您必须为每一个执行绪保留它们独立的空间,这是一种以空间换取时间与安全性的方法。
分享到:
评论

相关推荐

    java多线程设计模式详解(PDF及源码)

    Phase Termination——快把玩具收拾好,去睡觉吧 第11章 Thread-Specific Storage——每个线程的保管箱 第12章 Active Object——接受异步消息的主动对象 总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B...

    java多线程设计模式 (PDF中文版, 附源码)

    目录: 漫谈UML Introduction 1 Java语言的线程 Introduction 2 多线程...总结 多线程程序设计的模式语言 附录A 练习问题的解答 附录B Java的内存模型 附录C Java线程的优先级 附录D 线程相关的主要API 附录E 参考文献

    unix/linux多线程编程指南(sun技术文档)

    - 描述:一个典型的多线程编程模式,包括生产者线程(负责生成数据)和消费者线程(处理数据)。 - 实现方式:通常使用条件变量和互斥锁来协调生产者和消费者线程之间的通信。 - **读写锁(Reader-Writer Locks)...

    ACE技术论文集(已翻译为中文)

    第5章 C/C++线程专有存储(Thread-Specific Storage):用于访问“per-Thread”状态的对象行为模式 第6章主动对象(Active Object):用于并发编程的对象行为模式 第 7 章 ACE 反应器(Reactor)的设计和使用:用于...

    设计模式笔记

    - **Thread-Specific Storage(线程本地存储模式)**:每个线程都有自己的独立副本,可以避免线程间的竞争。 #### 三、实现差异 在不同的编程语言中实现设计模式时可能会有所差异。例如,本书作者在使用Java语言...

    良葛格DesignPattern学习笔记

    良葛格的《Design Pattern学习笔记》不仅涵盖了经典的GOF设计模式,还额外介绍了几种多线程模式,这使得这份学习笔记成为了一个宝贵的学习资源。下面将对其中的部分设计模式进行详细介绍。 #### 二、GOF设计模式 ...

    C++网络编程 卷2 基于ACE和框架的系统化复用

    ACE_TSS(Thread Specific Storage)则提供了线程局部存储的解决方案,避免了多线程环境下数据共享带来的复杂性。 此外,书中的“系统化复用”概念强调了软件设计的模块化和可重用性。作者会讲解如何利用ACE库中的...

    ACE.zip_ACE技术

    在对象间通信方面,ACE提供了ACE_TSS(Thread Specific Storage)机制,用于存储线程局部数据,以及ACE_Acceptor和ACE_Connector类,它们简化了服务器和客户端的建立连接过程。ACE_ServantActivator和ACE_Svc_...

    ACE(Adaptive Communication Environment)

    ACE_TSS(Thread Specific Storage)则允许开发者在多线程环境中为每个线程存储私有数据,确保数据的安全性和隔离性。 除了基本功能外,ACE还提供了一些高级特性,如服务质量(QoS)管理、网络容错和恢复机制、性能...

    ACE-6.1.1.tar

    ACE框架包含多个关键组件,如ACE_TSS (Thread Specific Storage)用于线程局部存储,ACE_Reactor模式处理事件,ACE_SOCK和ACE_SOCK_Dgram用于TCP/IP和UDP通信,ACE_Time_Value和ACE_DateTime支持时间管理和日期操作...

    ACE5.zip ACE5官网源码

    2. **ACE_TSS (Thread Specific Storage)**:ACE提供了一种线程局部存储的实现,通过`ACE_TSS`类,可以在线程级别存储数据,保证了数据在多线程环境下的安全性。 3. **ACE_Acceptor and ACE_Connector**: 这两个类...

    ACE库(linux)

    ACE_TSS(Thread Specific Storage)类允许开发者创建线程局部存储,解决了多线程环境下数据隔离的问题。 在分布式系统方面,ACE库支持CORBA(Common Object Request Broker Architecture),提供了一套完整的ORB...

    C++ 网络编程(经典版)

    3. **对象之间的通信**:ACE提供了一套完整的消息传递和对象间通信机制,如ACE_TSS(Thread Specific Storage)用于线程局部存储,ACE_Acceptor和ACE_Connector实现服务端和服务客户端的连接管理。 4. **网络协议的...

    ACE 程序员指南 源代码

    7. **分布式系统设计**:ACE_TSS(Thread Specific Storage)用于线程局部存储,ACE_Logger提供日志记录,ACE_WFMO_Reactor实现了Windows下的基于WaitFOrMultipleObjects的反应器。 8. **性能优化**:ACE_Dynamic_...

Global site tag (gtag.js) - Google Analytics