『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その５)

<img width="300" alt="javathread.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/165994/9d302410-0471-96c1-f097-d46649d17209.jpeg">

#Guarded Suspensionパターン
Guarded Suspensionパターンには**guarded wait**, **spin lock**などの呼び名がある。

```java:Request.java
public class Request {
     private final String name;
     public Request(String name) {
         this.name = name;
     }
     public String getName() {
         return name;
     }
     public String toString() {
         return "[ Request " + name + " ]";
     }
}
```

```java:RequestQueue.java
import java.util.Queue;
import java.util.LinkedList;

public class RequestQueue {
    private final Queue<Request> queue = new LinkedList<Request>();
    public synchronized Request getRequest() {
        while (queue.peek() == null) {
            try {
                wait(); // キューが空の時は待つ(ウェイトセットに入る)
            } catch (InterruptedException e) {
            }
        }
        return queue.remove();
    }
    public synchronized void putRequest(Request request) {
        queue.offer(request);
        notifyAll(); // 待っているスレッドに、キューにrequestが入ったことを知らせる
    }
}
```

```java:ClientThread.java
import java.lang.Math;

public class ClientThread extends Thread {
    private final RequestQueue requestQueue;
    public ClientThread(RequestQueue requestQueue, String name) {
        super(name);
        this.requestQueue = requestQueue;
    }
    public void run() {
        for (int i = 0; i <= 100; i++) {
            Request request = new Request("No." + i);
            System.out.println(Thread.currentThread().getName() + " put " + request);
            requestQueue.putRequest(request);
            try {
                Thread.sleep((int)(Math.random()*10));
            } catch (InterruptedException e) {
            }
        }
    }
}
```

```java:ServerThread.java
import java.lang.Math; 
 
public class ServerThread extends Thread { 
    private final RequestQueue requestQueue; 
    public ServerThread(RequestQueue requestQueue, String name) { 
        super(name); 
        this.requestQueue = requestQueue; 
    } 
    public void run() { 
        for (int i = 0; i <= 100; i++) { 
            Request request = requestQueue.getRequest(); 
            System.out.println(Thread.currentThread().getName() + " get " + request); 
            try { 
                Thread.sleep((int)(Math.random()*10)); 
            } catch (InterruptedException e) { 
            } 
        } 
    } 
}
```

```java:Main.java
public class Main { 
    public static void main(String[] args) { 
        RequestQueue requestQueue = new RequestQueue(); 
        new ClientThread(requestQueue, "A").start(); 
        new ServerThread(requestQueue, "B").start(); 
    } 
}
```

```text:実行結果
...
A put [ Request No.95 ]
B get [ Request No.91 ]
B get [ Request No.92 ]
A put [ Request No.96 ]
A put [ Request No.97 ]
B get [ Request No.93 ]
A put [ Request No.98 ]
B get [ Request No.94 ]
A put [ Request No.99 ]
B get [ Request No.95 ]
B get [ Request No.96 ]
B get [ Request No.97 ]
B get [ Request No.98 ]
B get [ Request No.99 ]
...
```

ClientThreadがSeverThreadにRequestのインスタンスを受け渡す。これは非常に簡単な**スレッド間通信**。ClientThreadやServerThreadのことを**能動オブジェクト**、RequestQueueのことを**受動オブジェクト**と呼ぶ。

ClientThreadがQueueにリクエストを投げ(put)、ServerThreadがQueueからリクエストを取り出す(get)。putとgetはsynchronizedで排他されている。

getRequesメソッドは最も古いリクエストを一つ取り出す。リクエストが一つもない場合は、他のスレッドがputRequestするまで待つ。queue.peek() != nullという条件つまりQueueが空でないという条件が満たされている必要がある。このような、満たされていなければならない条件のことをGuarded Suspensionパターンの**ガード条件**と呼ぶ。

putRequestメソッドは、リクエストを一つ追加する。その後notifyAllで待っているスレッドに知らせる。

waitとnotifyについては
[『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その１)](http://qiita.com/yoshi-yoshi/items/83ecc4476904fa144577)
を参照。

実行結果の通り、B(get)がA(put)を追い越すことはない。

##登場人物
GuardedObject役は、ガードされたメソッド(guardedMethod)を持っているクラス。ガード条件が満たされていればすぐに実行され、満たされていなければ待たされる。GuardedObjec役は、インスタンスの状態を変化させるメソッド(stateChangingMethod)を持つ場合がある。サンプルプログラムではRequestQueueクラスがこの役をつとめ、getRequestがguardedMethod、putRequestがstateChangingMethodに対応する。

---

関連
[『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その１)](http://qiita.com/yoshi-yoshi/items/83ecc4476904fa144577)
[『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その２)](http://qiita.com/yoshi-yoshi/items/792ed2e9dc09f63c5004#_reference-5f26b880e1c02b87a1d8)
[『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その３)](http://qiita.com/yoshi-yoshi/items/1d2c0e1279af4adb2e9b)
[『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その４)](http://qiita.com/yoshi-yoshi/items/3b642f91b27120cc4b15)