⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadspecificstorage.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>





  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">





  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">





  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">





  
  
  
  
  
  <title>Thread-Specific Storage 模式</title>
</head>


<body>





<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>





<h1><a href="CppGossip.html">Design Pattern:&nbsp;Thread-Specific Storage 模式</a></h1>

无论如何,要编写一个多执行绪安全(thread-safe)的程式总是困难的,为了使用的共用资源,您必须小心
的对共用资源进行同步,同步带来一定的效
能延迟,而另一方面,在处理同步的时候,又要注意物件的锁定与释放,避免产生死结,种种因素都使得编写多执行绪程式变得困难。<br>

<br>
Thread-Specific
Storage模式尝试从另一个角度来解释多执行绪共用资源的问题,其思考点很简单,即然共用资源这么困难,那么就干脆不要共用,何不为每个执行绪创造一
个资源的复本,将每一个执行绪存取资料的行为加以隔离,其实现的方法,就是给予每一个执行绪一个特定空间来保管该执行绪所独享的资源,也因此而称之为
Thread- Specific Storage模式。<br>

<br>
在Java中可以使用java.lang.ThreadLocal来实现这个模式,这个类别是从1.2之后开始提供,不过先来看看,如何自行实
现一个简单的ThreadLocal类别:<br>

<ul>
  <li> ThreadLocal.java </li>
</ul>

<pre>import java.util.*;<br><br>public class ThreadLocal {<br>    private Map storage = <br>                Collections.synchronizedMap(new HashMap());<br><br>    public Object get() {<br>        Thread current = Thread.currentThread();<br>        Object o = storage.get(current);<br><br>        if(o == null &amp;&amp; !storage.containsKey(current)) {<br>            o = initialValue();<br>            storage.put(current, o);<br>        }<br><br>        return o;<br>    }<br><br>    public void set(Object o) {<br>        storage.put(Thread.currentThread(), o);<br>    }<br><br>    public Object initialValue() {<br>        return null;<br>    }<br>} <br></pre>

<br>
可以看到程式中使用执行绪本身作为key值,并将所获得的资源放在Map物件中,如果第一次使用get(),也配置一个空间给执行绪,而
initialValue()可以用来设定什么样的初值要先储存在这个空间中,在这边先简单的设定为null。<br>

<br>
现在假设有一个原先在单执行绪环境下的资源SomeResource,现在考虑要该其在多执行绪环境下使用,若不想考虑复杂的执行绪共用互斥问题,此时可以使用ThreadLocal类别来使用SomeResource,例如:<br>

<ul>
  <li> Resource.java </li>
</ul>

<pre>public class Resource {<br>    private static final ThreadLocal threadLocal = <br>                                        new ThreadLocal();<br><br>    public static SomeResource getResource() {<br>        SomeResource resource =<br>                        (SomeResource) threadLocal.get();<br><br>        if(resource == null) {<br>            resource = new SomeResource();<br>            threadLocal.set(resource);<br>        }<br><br>        return resource;<br>    }<br>} <br></pre>

<br>
上面所实作的ThreadLocal类别只是一个简单的示范,您可以使用java.lang.ThreadLocal来实
现Thread- Specific
Storage模式,以获得更好的效能,在这边简单的示范一个Log程式,它可以记录每个执行绪的活动,所使用的是
java.util.logging中的类别:<br>

<ul>
  <li> SimpleThreadLogger.java </li>
</ul>

<pre>import java.io.*;<br>import java.util.logging.*;                            <br> <br>public class SimpleThreadLogger {<br>    private static final ThreadLocal threadLocal = <br>                                         new ThreadLocal();<br><br>    public static void log(String msg) {<br>        getThreadLogger().log(Level.INFO, msg);<br>    }<br><br>    private static Logger getThreadLogger() {<br>        Logger logger = (Logger) threadLocal.get();<br><br>        if(logger == null) {<br>            try {<br>                logger = Logger.getLogger(<br>                           Thread.currentThread().getName());<br>                // Logger 预设是在主控台输出<br>                // 我们加入一个档案输出的Handler<br>                // 它会输出XML的记录文件<br>                logger.addHandler(<br>                    new FileHandler(<br>                           Thread.currentThread().getName() <br>                           + ".log"));<br>            }<br>            catch(IOException e) {}<br><br>            threadLocal.set(logger);<br>        }<br><br>        return logger;<br>    }<br>} <br></pre>

<br>
可以使用下面这个程式来测试:<br>

<ul>
  <li> LoggerTest.java </li>
</ul>

<pre>public class LoggerTest {<br>    public static void main(String[] args) {<br>        new TestThread("thread1").start();<br>        new TestThread("thread2").start();<br>        new TestThread("thread3").start();<br>    }<br>}<br><br>class TestThread extends Thread {<br>    public TestThread(String name) {<br>        super(name);<br>    }<br><br>    public void run() {<br>        for(int i = 0; i &lt; 10; i++) {<br>            SimpleThreadLogger.log(getName() + <br>                                     ": message " + i);<br>            try {<br>                Thread.sleep(1000);<br>            }<br>            catch(Exception e) {<br>                SimpleThreadLogger.log(e.toString());<br>            }<br>        }<br>    }<br>} <br></pre>

<br>
执行LoggerTest可以在主控台上看到输出,并可以在同一目录下找到三个log档,分别记录了三个执行绪的活动,透过
ThreadLocal,不用撰写复杂的执行绪共用互斥逻辑。<br>

<br>
Thread-Specific
Storage模式的意义之一,就是“有时不共用是好的”,如果共用会产生危险,那就不要共用,当然,这种方式所牺牲掉的就是空间,您必须为每一个执行
绪保留它们独立的空间,这是一种以空间换取时间与安全性的方法。




</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -