原理
目を覚ますのを待っています
ウェイクアップ待機メカニズムは、スレッド間の通信の問題を解決するために使用されます。使用される3つの方法の意味は次のとおりです。
- wait:スレッドはアクティブでなくなり、スケジューリングに参加しなくなり、待機セットに入ります。したがって、CPUリソースを浪費したり、ロックを競合したりすることはありません。この時点でのスレッドのステータスはWAITINGです。また、他のスレッドが特別なアクションを実行するのを待つ必要があります。つまり、このオブジェクトを待機しているスレッドが待機セットから解放され、準備完了キューに再び入ることを「通知」します。
- 通知:通知されたオブジェクトの待機セットで解放するスレッドを選択します。たとえば、レストランに空席ができた後、最長の食事を待っていた顧客が最初に着席します。
- notifyAll:通知されたオブジェクトの待機セットのすべてのスレッドを解放します。
注:
待機中のスレッドのみが通知されても、中断された場所が同期ブロック内にあり、現時点ではロックを保持していないため、通知されたスレッドはすぐに実行を再開できません。そのため、彼女は取得を試みる必要があります。再びロックし(他のスレッドとの競合に直面する可能性があります)、成功した後にのみ、waitメソッドへの最初の呼び出しの後の場所で実行を再開できます。
要約は次のとおり
です。ロックを取得できる場合、スレッドはWAITING状態からRUNNABLE状態に変わります。
そうでない場合、待機セットからエントリセットに入ると、スレッドはWAITING状態からBLOCKED状態に再び変わります。
waitメソッドとnotifyメソッドを呼び出すときに注意が必要な詳細
- waitメソッドとnotifyメソッドは、同じロックオブジェクトから呼び出す必要があります。理由:対応するロックオブジェクトは、notifyを介して同じロックオブジェクトによって呼び出されたwaitメソッドの後にスレッドをウェイクアップできます。
- waitメソッドとnotifyメソッドは、Objectクラスのメソッドです。理由:ロックオブジェクトは任意のオブジェクトにすることができ、任意のオブジェクトのクラスはObjectクラスを継承します。
- waitメソッドとnotifyメソッドは、同期コードブロックまたは同期関数で使用する必要があります。理由:これらの2つのメソッドは、lockオブジェクトを介して呼び出す必要があります。
分析
包子の糸は蒸し饅頭を作り、食品の糸は蒸し饅頭を消費します。パンがない場合(パンのステータスがfalseの場合)、フードイータースレッドは待機し、Baozipuスレッドはバンを生成し(つまり、バンのステータスがtrue)、フードイータースレッドに通知します(待機状態の食べ物が出ます)、すでにパンがあるので、ブンジプ糸待ち状態に入ります。次に、食物を食べるスレッドがさらに実行できるかどうかは、ロックの取得に依存します。食通が鍵をかけると、蒸し饅頭を食べる動作を実行し、蒸し饅頭が終了し(蒸し饅頭の状態が偽)、包子糸が通知され(蒸し饅頭屋の待機状態が解除される)、食通の糸が待ちに入る。Baozipuスレッドがさらに実行できるかどうかは、ロックの取得に依存します。
コード
Baozi_Baoziクラスの属性
public class Baozi {
private String pier;
private String xianer;
private boolean isBaozi = false;
public Baozi(String pier, String xianer, boolean isBaozi) {
this.pier = pier;
this.xianer = xianer;
this.isBaozi = isBaozi;
}
public Baozi() {
}
public String getPier() {
return pier;
}
public void setPier(String pier) {
this.pier = pier;
}
public String getXianer() {
return xianer;
}
public void setXianer(String xianer) {
this.xianer = xianer;
}
public boolean isBaozi() {
return isBaozi;
}
public void setBaozi(boolean baozi) {
isBaozi = baozi;
}
}
プロデューサークラス_プロデュースクラス
public class Produce extends Thread{
Baozi bz ;
public Produce(Baozi bz){
this.bz=bz;
}
@Override
public void run() {
int count = 0;
while (true){
synchronized (bz){
if(bz.isBaozi()==true) {
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("老板正在做包子");
if(count%2 == 0 ){
bz.setPier("厚皮儿");
bz.setXianer("三鲜馅儿");
}else{
bz.setPier("薄皮儿");
bz.setXianer("韭菜馅儿");
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(bz.getXianer()+bz.getPier()+"的包子做好了");
count++;
bz.setBaozi(true);
bz.notify();
}
}}}
コンシューマーclass_Eatクラス
public class Eat extends Thread{
Baozi bEat ;
public Eat(Baozi bEat){
this.bEat=bEat;
}
@Override
public void run() {
while (true){
synchronized (bEat){
if(bEat.isBaozi()==false) {
try {
bEat.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("吃货吃包子");
System.out.println("吃货吃完包子");
bEat.setBaozi(false);
System.out.println("===========================================");
System.out.println();
bEat.notify();
}
}
}
}
テスト実装クラス
public class main {
public static void main(String[] args) {
Baozi bz =new Baozi();
Produce p = new Produce(bz);
Eat e = new Eat(bz);
p.start();
e.start();
}
}
結果
次のように循環します。
老板正在做包子
三鲜馅儿厚皮儿的包子做好了
吃货吃包子
吃货吃完包子
===========================================
老板正在做包子
韭菜馅儿薄皮儿的包子做好了
吃货吃包子
吃货吃完包子
===========================================