同時メカニズムに基づいて生産者-消費者モデルを実現する
3536 ワード
前回はjdkの元の同期メカニズムを用いて生産者-消費者モデルを実現したが、今回はjdk 1に変更した.5で提供される関連する同時クラスは、生産者-消費者モデルを実現する.
ReentrantLockクラス の役割はsynchronizedコードブロックとあまり差がなく、反発を実現するために使用されます.もちろん、両者には違いがあります.
Conditionインタフェース それはawait()、signal()、signalAll()などの方法を提供し、Objectクラスのwait()、signal()とsignalAll()の方法と同じである.インタフェースであるため、newはできません.ReentrantLockクラスのnewConditionメソッドを使用して、ReentrantLockオブジェクトに関連付けられたConditionオブジェクト(実際にはConditionObjectクラスオブジェクト)を取得する必要があります.
同様に、Conditionのawait()、signal()、signalAll()は、呼び出すには対応するReentrantLockロックを取得する必要があります.
ここでは、同じReentrantLockオブジェクトを使用してnewConditionを複数回呼び出して複数のConditionオブジェクトを取得し、より複雑な同期関係を実現することができますが、Objectクラスを使用するのは1つのConditionオブジェクトのみに相当します.もちろん、異なるConditionオブジェクトの中で、待機と起動は対応しなければならない.例えば、newConditionメソッドを2回呼び出し、2つのConditionオブジェクトcondition 1とcondition 2を得た.もし私がスレッドAでcondition 1を呼び出したら.await()は、スレッドBがcondition 2を呼び出す.signal()では、スレッドAは必ず起動されず、condition 1を呼び出すべきである.Signal()スレッドAが呼び覚まされる可能性がありますが、なぜ可能とは限らないのでしょうか.なぜならsignal()はObjectクラスのnotify()と同じであり、システムは待機セットのスレッドをランダムに起動し、私たちのスレッドAが選択されるとは限らないからです.
1.コードからReentrantLockを使用する欠点の一つは、lockが完了するたびにfinallyブロックでunLockを実行しなければならないということです.これは私たちがいつでも覚えているわけではありません.
転載は原文の住所を明記してください.http://blog.csdn.net/u012619640/article/details/48090939
まず2つのクラス(インタフェース)について説明します。
同様に、Conditionのawait()、signal()、signalAll()は、呼び出すには対応するReentrantLockロックを取得する必要があります.
ここでは、同じReentrantLockオブジェクトを使用してnewConditionを複数回呼び出して複数のConditionオブジェクトを取得し、より複雑な同期関係を実現することができますが、Objectクラスを使用するのは1つのConditionオブジェクトのみに相当します.もちろん、異なるConditionオブジェクトの中で、待機と起動は対応しなければならない.例えば、newConditionメソッドを2回呼び出し、2つのConditionオブジェクトcondition 1とcondition 2を得た.もし私がスレッドAでcondition 1を呼び出したら.await()は、スレッドBがcondition 2を呼び出す.signal()では、スレッドAは必ず起動されず、condition 1を呼び出すべきである.Signal()スレッドAが呼び覚まされる可能性がありますが、なぜ可能とは限らないのでしょうか.なぜならsignal()はObjectクラスのnotify()と同じであり、システムは待機セットのスレッドをランダムに起動し、私たちのスレッドAが選択されるとは限らないからです.
生産者-消費者モデル(ブロックキュー):
public class ProducerConsumerCondition {
private int bufSize;
private int[] buf;
private int currentSize;
private ReentrantLock mainLock = new ReentrantLock();
private Condition putCondition = mainLock.newCondition();
private Condition getCondition = mainLock.newCondition();
public ProducerConsumerCondition() {
this(10);
}
public ProducerConsumerCondition(int bufSize) throws IllegalArgumentException{
this.bufSize = bufSize;
if(bufSize < 0) {
throw new IllegalArgumentException("bufSize can't less zero");
}
buf = new int[bufSize];
}
public void put(int v) throws InterruptedException{
mainLock.lock();
try {
while(currentSize >= bufSize) {
putCondition.await();
}
if(currentSize < bufSize) {
buf[currentSize++] = v;
getCondition.signal();
}
} catch(InterruptedException e) {
throw e;
} finally {
mainLock.unlock();
}
}
public int get() throws InterruptedException{
mainLock.lock();
try {
while(currentSize == 0) {
getCondition.await();
}
if(currentSize > 0) {
int temp = buf[currentSize - 1];
currentSize--;
putCondition.signal();
return temp;
}
} catch(InterruptedException e) {
throw e;
} finally {
mainLock.unlock();
}
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[");
sb.append("queue's length=" + currentSize);
sb.append(" ");
for(int i = 0; i < currentSize - 1; i++) {
sb.append(buf[i] + ",");
}
if(currentSize > 0) {
sb.append(buf[currentSize - 1]);
}
sb.append("]");
return sb.toString();
}
}
説明
1.コードからReentrantLockを使用する欠点の一つは、lockが完了するたびにfinallyブロックでunLockを実行しなければならないということです.これは私たちがいつでも覚えているわけではありません.
転載は原文の住所を明記してください.http://blog.csdn.net/u012619640/article/details/48090939