Java多线程设计模式(7)线程独有储藏库模式

一  Thread-Specific Storage Pattern

  Thread-Specific Storage Pattern指的就是线程独有的储藏库,针对每个线程提供内存空间的意义。这种模式只有一个入口,但是内部会对每个线程提供特有的存储空间。

  Thread-Specific Storage Pattern的所有参与者:

  1,Client参与者,提出具体工作的,将该具体工作委托给TSObjectProxy参与者。

  2,TSObjectProxy参与者,这个主要是接受工作请求的,它会处理多个Client的工作,它一般都包括了TSObjectCollection。一般都是先使用TSObjectCollection参与者,取得Client参与者所对应的TSObject参与者,并将Client具体的工作委托给TSObject参与者。

  3,TSObjectCollection参与者,这个主要就是线程独有对象的集合,它利用线程键值对来存储着执行Client参与者线程所对应的TSObject参与者。一般都是利用ThreadLocal来实现。

  4,TSObject参与者,线程独有的对象,存放着线程特有的信息,尽管会为多个线程使用,但是不需要利用synchronized来进行互斥操作。

  TSObject参与者与TSObjectProxy参与者具有相同的接口。

  具体的模式如下图所示。虽然多个不同的ClientThread来请求同一个对象Log即TSObjectProxy参与者,但是Log会为每个请求线程利用ThreadLocal来分配独立的TSLog对象。所有线程所共享的是TSObjectProxy参与者。

  Java多线程设计模式(7)线程独有储藏库模式

关于ThreadLocal小讲:

   每一个线程都拥有自己独立的存储空间,也就是方法局部变量的堆栈,在方法里分配的局部变量都是线程所独有的,但是这些变量一退出方法就会消失了。ThreadLocal则是与方法调用无关,它为线程分配特有空间。

   ThreadLocal实例如一个保管箱间,它通过线程键值对来存储与线程特定的信息。每个线程的保管箱,都放置在ThreadLocal中。

   ThreadLocal该类提供了线程局部变量。ThreadLocal的局部变量在被多个线程使用时候,每个线程只能拿到该变量的一个副本。

   在ThreadLocal类型的变量内部有个ThreadLocalMap,它提供了一个注册表来注册与当前线程相关的信息,ThreadLocal类型的变量对外部表现是一个,但是内部确实管理着一群对象的集合。

   在利用get与set的时候,都会在两个方法体中首先获取Thread t = Thread.currentThread();,然后在该线程的内部进行操作。不用担心其他线程对于该线程的破坏访问。在使用两个方法的时候务必要分清是属于那个线程中的操作。

   在这个模式中,客户端线程所共享的是TSObjectProxy参与者,但是实际的工作则是在TSObject参与者分配给相应的线程后才进行的,就是利用TSObjectProxy参与者来分配不被共享的TSObject参与者。对于TSObject完全不用做任何的互斥synchronized操作。

代码示例:

仅仅列出TSObjectProxy的架构模式

Log代表了TSObjectProxy参与者,供多个线程进行访问,最后将具体的操作委托给TSObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package whut.specificstorage;
//负责产生保管箱间的类
public class Log {
    //首先利用static final修饰
    //保证了所有访问该类的线程都只使用一个唯一的且不变的保管箱间。
    private static final ThreadLocal tsLogCollections=new ThreadLocal();
                                         
    //不用使用synchronized,因为在使用get和set时候,会字段判别当前所属的线程
    //取得当前线程特有的Log
    private static TSLog getTSLog()
    {
        TSLog tsLog=(TSLog)tsLogCollections.get();
                                             
        //如果线程是第一次调用,就建立新文件夹以及注册log
        if(tsLog==null)
        {
            tsLog=new TSLog(Thread.currentThread().getName()+"-log.txt");
            tsLogCollections.set(tsLog);
        }
        return tsLog;
    }
                                         
    //加入一条LOG
    public static void println(String s)
    {
           getTSLog().println(s);
    }
    //关闭LOG
    public static void close()
    {
        getTSLog().close();
    }
}

   该Log类具有TSobject相同的方法,客户端线程每次请求该类,进而为请求的线程分配属于该线程的TSObject对象,每次的工作都是最终委托给TSObject来真正的执行。TSObjectProxy和TSObject类的方法与字段不需要进行任何的synchronized处理。




本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1206623


上一篇:组件的props


下一篇:小白学shiro