keep moving!

          We must not cease from exploration. And the end of all our exploring will be to arrive where we began and to know the place for the first time.
          隨筆 - 37, 文章 - 2, 評論 - 3, 引用 - 0
          數據加載中……

          Design Pattern: 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模式的意義之一,就是「有時不共用是好的」,如果共用會產生危險,那就不要共用,當然,這種方式所犧牲掉的就是空間,您必須為每一個執行緒保留它們獨立的空間,這是一種以空間換取時間與安全性的方法。

          張金鵬 2007-04-17 10:59 發表評論

          文章來源:http://www.aygfsteel.com/jesson2005/articles/111204.html

          posted on 2008-09-07 11:06 大石頭 閱讀(165) 評論(0)  編輯  收藏 所屬分類: 多線程

          主站蜘蛛池模板: 桃园县| 个旧市| 许昌县| 手机| 姜堰市| 涞源县| 临澧县| 思茅市| 晋宁县| 苗栗市| 岳普湖县| 江西省| 延边| 嘉定区| 平顶山市| 金华市| 曲沃县| 衢州市| 锡林郭勒盟| 阿尔山市| 崇义县| 淮北市| 瑞昌市| 巴林左旗| 天水市| 西吉县| 青岛市| 碌曲县| 巫溪县| 阿拉善左旗| 漳州市| 彰化市| 南陵县| 通山县| 富蕴县| 信阳市| 吉隆县| 四平市| 东明县| 大新县| 伽师县|