【デザインパターン】【非同期】Guarded Suspensionパターン

Guarded Suspensionパターン

 * 処理要求に対して、実行可能な状態になるまで待機させるデザインパターン
  => インスタンスが適切な状態になるまで、ガード条件を使ってスレッドを待たせる
 * ガード条件が変化したことをスレッドの通知(notify/notifyAll)

関連するパターン

 * Balkingパターン:ガード条件が満たされないなら待たずに返る場合
http://blogs.yahoo.co.jp/dk521123/34200869.html

補足:スレッドの同期

http://blogs.yahoo.co.jp/dk521123/32058018.html
 * wait() : 現在のスレッドを待機させる。
 * notify() : wait()によって待機中であるスレッドの1つを再開。プログラム側から指定することはできない。
 * notifyAll() : wait()によって待機中であるすべてのスレッドを再開。

サンプル

Main.java

public class Main {
   public static void main(String[] args) {
      TaskManager manager = TaskManager.getInstance();
      for (int i = 1; i <= 10; i++) {
         System.out.println("workThread(" + i + ") put!");
         TaskThread workThread = new TaskThread(manager, i);
         manager.putTask(workThread);
         System.out.println("workThread(" + i + ") Start!");
         TaskThread workThread2 = manager.getTask();
         workThread2.start();
      }
   }
}

TaskManager.java

import java.util.concurrent.atomic.AtomicBoolean;

public class TaskManager {
   private static TaskManager manager = new TaskManager();
   private TaskQueue taskQueue;
   private AtomicBoolean isAvailable = new AtomicBoolean(true);
   
   private TaskManager() {
      this.taskQueue = new TaskQueue();
   }

   public static TaskManager getInstance() {
      return TaskManager.manager;
   }
   
   public TaskThread getTask() {
      return this.taskQueue.getTask();
   }
   public synchronized void putTask(TaskThread task) {
      this.taskQueue.putTask(task);
   }
   
   /**
    * ロック
    */
   public synchronized void lock() {
      while (!this.isAvailable.get()) {
         try {
            this.wait();
         } catch (InterruptedException e) {
         }
      }
      this.isAvailable.set(false);
   }

   /**
    * ロック解放
    */
   public synchronized void unlock() {
      this.isAvailable.set(true);
      this.notify();
   }
}

TaskThread.java

public class TaskThread extends Thread {
   private TaskManager manager;
   private int id;

   // コンストラクタ
   public TaskThread(TaskManager manager, int id) {
      this.manager = manager;
      this.id = id;
   }

   public void run() {
      this.manager.lock();
      // 処理の実行
      try {
         System.out.println("Thread(" + id + ") Run!");
         Thread.sleep(1000);
         System.out.println("Thread(" + id + ") End!");
      } catch (Exception e) {
         e.printStackTrace();
      }
      this.manager.unlock();
   }
}

TaskQueue.java

import java.util.Queue;
import java.util.LinkedList;

public class TaskQueue {
   private final Queue<TaskThread> queue = new LinkedList<TaskThread>();

   public synchronized TaskThread getTask() {
      while (this.queue.peek() == null) {
         try {
            this.wait();
         } catch (InterruptedException e) {
         }
      }
      return this.queue.remove();
   }

   public synchronized void putTask(TaskThread task) {
      this.queue.offer(task);
   }
}



関連記事

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

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

Worker Thread パターン

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