一 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参与者。
关于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