【デザインパターン】【非同期】Thread-Specific Storage パターン

目的

 * 他のスレッドからアクセスさせないようにする

ポイント

 * java.lang.ThreadLocal を使う
  => スレッド毎の値を保持するためのクラス
  => 詳細は以下の関連記事を参照のこと。
http://blogs.yahoo.co.jp/dk521123/36396466.html

サンプル

 * スレッドごとのロガー(ThreadLocalを使って、スレッドごとにログを出力するサンプル)

Main.java

public class Main {

   public static void main(String[] args) {
      new ClientThread("Sample0001").start();
      new ClientThread("Sample0002").start();
      new ClientThread("Sample0003").start();
   }
}

ClientThread.java

public class ClientThread extends Thread {
    public ClientThread(String name) {
        super(name);
    }
    public void run() {
        System.out.println(getName() + " BEGIN");
        for (int i = 0; i < 10; i++) {
            Log.println("i = " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
        Log.close();
        System.out.println(getName() + " END");
    }
}

ThreadLogger.java

import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadLogger {
   private SimpleDateFormat dateFormatter = null;
   private PrintWriter writer = null;
   
   public ThreadLogger(String fileName) {
      try {
         this.dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
         this.writer = new PrintWriter(new FileWriter(fileName));
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
   
   public void println(String value) {
      this.writer.println(this.dateFormatter.format(new Date()) + " : " + value);
   }
   
   public void close() {
      this.writer.println("=== Close ===");
      this.writer.close();
   }
}

Logger.java

public class Logger {
   private static final ThreadLocal<ThreadLogger> logs = new ThreadLocal<ThreadLogger>();
   
   public static void println(String value) {
      ThreadLogger log = Logger.getThreadLogger();
      log.println(value);
   }
   public static void close() {
      ThreadLogger log = Logger.getThreadLogger();
      log.close();
   }
   
   private static ThreadLogger getThreadLogger() {
      ThreadLogger log = Logger.logs.get();
      if (log == null) {
         log = new ThreadLogger(Thread.currentThread().getName() + ".log");
         Logger.logs.set(log);
      }
      
      return log;
   }
}

出力結果

コンソール画面

Sample0001 BEGIN
Sample0002 BEGIN
Sample0003 BEGIN
Sample0001 END
Sample0003 END
Sample0002 END

Sample0001.log(Sample0002、3.log)

2014/12/14 03:39:36.131 : i = 0
2014/12/14 03:39:36.232 : i = 1
2014/12/14 03:39:36.332 : i = 2
2014/12/14 03:39:36.432 : i = 3
2014/12/14 03:39:36.532 : i = 4
2014/12/14 03:39:36.633 : i = 5
2014/12/14 03:39:36.734 : i = 6
2014/12/14 03:39:36.835 : i = 7
2014/12/14 03:39:36.935 : i = 8
2014/12/14 03:39:37.036 : i = 9
=== Close ===


関連記事

デザインパターン / マルチスレッド の分類 ~目次~

http://blogs.yahoo.co.jp/dk521123/34195603.html

Active Object パターン

http://blogs.yahoo.co.jp/dk521123/23819359.html

java.lang.ThreadLocal について

http://blogs.yahoo.co.jp/dk521123/36396466.html