クラスライブラリ応用

スレッド

今回は「Java言語プログラミングレッスン 下」を参照します。 この本に掲載されているサンプルプログラムは著者のサイトからダウンロードできますが、 文字コードが Shift JIS であるため、UTF-8 に変換したものを以下に置いておきます。

スレッドの協調

前回、1つのオブジェクトを複数のスレッドで利用する場面を扱いました。 ある1つのスレッドが利用しているときには他のスレッドを待たせる、 というシンプルな排他制御でした。

今回は、もっと細やかな制御が必要な場合を扱います。

「生産者 / 消費者」問題

日本の政治においては、生産者中心の行政が行われてきたと言われています。 そのため、消費者の視点から政策全般を監視するために、 2009年9月、消費者庁が設置されました。

マルチスレッドプログラミングにおける「生産者 / 消費者」問題とは、 データ (data) の生産者 (Producer) と消費者 (Consumer) を独立のスレッドとして考え、 生産と消費が連動して進むようにプログラムを設計するにはどうしたらよいか、 という話です。

生産者はデータを次々と生産し、消費者は次々とデータを消費するものとします。 生産と消費のスピードのバランスがとれていればよいのですが、 生産のスピードが早ければ在庫過剰に、 消費のスピードが早ければ売りきれて入手不能になります。 在庫過剰になった場合は、生産者は在庫がある程度はけるまで生産を停止しなければなりません。 在庫切れの場合には、消費者は次に生産されるまで待たなければなりません。

市場を固定サイズの queue と考え、生産者と消費者でこれを共有しているモデルを考えます。 生産者はデータを生産すると、queue に追加をします。 消費者は queue からデータを取得し消費します。 queue が一杯になると、生産者は生産を止めて待たなければなりません。 queue が空になると、消費者はデータが queue に追加されるまで待たなければなりません。

このように待ち(wait)が発生するとき、 生産者や消費者はブロック(block)される、と言います。

教科書 p.174 から説明のあるサンプルプログラム List 16-11 では、 配列(リングバッファ)による queue を生産者と消費者で共有しています。 消費者は queue が空の時、生産者は queue が一杯の時、待ち状態に入ります。 状況が変わると通知され、動き出します。 これらの動きを、wait / notify (notifyAll) メソッドにより実現しています。

BlockingQueue / BlockingDeque

Javaでは、並行プログラミングでよく使用されるクラス群が java.util.concurrent パッケージとして提供されています。

この中に、必要に応じてブロックする機能を持った queue である BlockingQueue、 あるいは deque (両端キュー)である BlockingDeque というインタフェースがあり、 実装クラスとして ArrayBlockingQueue, LinkedBlockingQueue, LinkedBlockingDeque などが用意されています。

教科書では ArrayBlockingQueue を使用した例が付録F(p.368)にあります。

wait や notify をする部分が組み込まれていて、自前でする必要がないため便利です。