multi thread 5

Producer-Consumer パターン

Dataを作るスレッド(Producer)とDataを使うスレッド(Consumer)が動いており,ProducerからConsumerへDataを渡すことを考える.

この協調動作(橋渡し)はChannelが行う.Channel は

  • Producer からDataを受け取る部分
  • Consumer にDataを渡す部分

の二つの”Guarded Suspension”パターン(Blocking処理)からなる.すなわち二つの排他制御が協調動作を行う.

言うまでもなく,ここで大事なのはProducerでもConsumerでもなくChannelである.

public producer {
    public void run() {
        channel.put(production)
    }
}
public consumer {
    public void run() {
        consumption = channel.take()
    }
}
public channel {
    this.buffer = new Product[bufferSize]
    public synchronized void put(Product production) throws InterruptException {
        while (the buffer is not full yet) {
            wait()
        }
        (put on the buffer)
    }
    public synchronized Product take() throws InterruptException {
        while (the buffer is empty) {
            wait()
        }
        (take from the buffer)
    }
}

channel の中に二つの”Guarded Suspension”パターンが使われていることが分かる

bufferに格納する順番は色々考えられる

  1. Queue:First In First Out. 古いものを先に取り出す
  2. Stack:Last In First Out. 新しいものを先に取り出す
  3. Priority queue:優先順位を別に与えておき,それでソートする

ちなみに,InterruptedExceptionは「時間はかかるかもしれないがキャンセルできるメソッド」につけると良い

Javaの標準ライブラリでInterruptedExceptionがついたメソッドのうち有名なものは

  • java.lang.Object の wait()
  • java.lang.Thread の sleep()
  • java.lang.Thread の join()

だが,これはそれぞれ

  • notify/notifyAll を待っているのをキャンセル(wait setにいたスレッドはロックを再び取り直す)
  • 指定した時間だけ停止しているのをキャンセル
  • 別スレッドの終了を待っているのをキャンセル

させると,InterruptedExceptionが投げられる.キャンセルさせるには普通interrupt()を呼ぶが,これは厳密にはinterrupt()はスレッドのインタラプト状態を変えるだけのメソッドらしい.なので,インタラプト状態かどうか調べたければisInterrupted()をすれば良い.

実際にはjava.util.concurrentパッケージにBlockingQueueがあり,これを使うのが便利かもしれない.

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中