分析は、生産者と消費者の古典的なケースをスレッド
1 / ** 2 共享数据 3 * / 4 クラスリソース 5 { 6 プライベート文字列名。 7 プライベート int型のカウント= 1 ; 8 プライベート ブールフラグ= 偽; 9 10 パブリック 同期 ボイド集合(文字列名) 11 { 12の 場合(フラグ) 13 のtry { この .WAIT();} キャッチ(InterruptedExceptionある電子){} 14 この .nameの=名+カウント; 15 数++ ; 16 のSystem.out.println(にThread.currentThread()のgetName()+ "...生产者..." +。この.nameの); 17 フラグ= 真。 18 )(通知します。 19 } 20 21 公共 同期 ボイドアウト() 22 { 23 であれば(!フラグ) 24 のtry { この .WAIT();} キャッチ(InterruptedExceptionある電子){} 25 。のSystem.out.println(にThread.currentThread()のgetName( )+ "==消费者==" + この.nameの) 26は 、フラグ= falseに、 27は、 通知(); 28 } 29 } 30 31である // カスタム・スレッド・タスク(プロデューサスレッド) 32 クラスプロデューサー実装Runnableを 33であり 、{ 34が プライベートリソースR< 35 36 プロデューサー(リソースR&LT) 37 [ { 38は この .R = R< 39 } 40 公共 ボイドRUN() 41はある { 42は 、一方(真の) 43は 、{ 44が r.set( "製品" ); 45 } 46 } 47 } 48 // 定義されたタスク・スレッド(スレッド消費者) 49 クラスの消費者実装はRunnableを 50 { 51が プライベートリソースR< 52である 53れている 消費者(リソースR&LT) 54です { 55 この .R = R< 56である } 57が 58 公共 ボイドRUN() 59 { 60 ながら、(真の) 61は { 62であり ; r.out() 63である } 64 } 65 } 66 67 クラスProducerConsumerDemo 68 { 69 公共 静的 ボイドメイン(文字列[]引数) 70 { 71である // インスタンスの共有リソース 72 のリソース= R&LT 新しい新しいリソース()。 73 // インスタンス化タスクをスレッド、共有リソースを指定する 74 プロデューサーP = 新しい新プロデューサ(R&LT); 75 コンシューマC = 新しい新しい消費者(R&LT); 76 //スレッドの例として、タスク指定されたスレッド 77 スレッド= T0 新しい新しいスレッド(P); 78 スレッド= T1 新しい新しいスレッド(P)、 79 スレッドT2 = 新しい新しいスレッド(C); 80 スレッドT3 = 新しい新しいスレッド(C); 81 // オープンスレッド、実行タスクのスレッドの実行方法 82 t0.start(); 83 t1.start(); 84 t2.start(); 85 t3.start(); 86 } 87 }
結果:
結果の分析:
それでは、どのその後、裁判官フラグそれ?同時に
コードは以下の通りであります:
1 class Resource 2 { 3 private String name; 4 private int count=1; 5 private boolean flag=false; 6 7 public synchronized void set(String name) // 有两个线程t0 t1 8 { 9 while(flag) 10 try{this.wait();}catch(InterruptedException e){} 11 this.name=name+count; 12 count++; 13 System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name); 14 flag = true; 15 notify(); 16 } 17 18 public synchronized void out() // 有两个线程t2 t3 19 { 20 while(!flag) 21 try{this.wait();}catch(InterruptedException e){} 22 System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name); 23 flag = false; 24 notify(); 25 } 26 }
结果出现死锁:
结果分析:
通过分析,那能不能每次唤醒只唤醒对方线程(如生产者线程只唤醒消费者线程,消费者线程只唤醒生产者线程),查看Object对象方法中没有,但是有一个notifyAll()方法,实在不行就把所有阻塞线程(相同同步锁的线程)都唤醒。
1 class Resource 2 { 3 private String name; 4 private int count=1; 5 private boolean flag=false; 6 7 public synchronized void set(String name) // 有两个线程t0 t1 8 { 9 while(flag) 10 try{this.wait();}catch(InterruptedException e){} 11 this.name=name+count; 12 count++; 13 System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name); 14 flag = true; 15 notifyAll(); 16 } 17 18 public synchronized void out() // 有两个线程t2 t3 19 { 20 while(!flag) 21 try{this.wait();}catch(InterruptedException e){} 22 System.out.println(Thread.currentThread().getName() + "==消费者==" + this.name); 23 flag = false; 24 notifyAll(); 25 } 26 }
结果:
这样就可以了。
总结:
if判断只能判断一次,如果执行等待方法,下次唤醒的线程获取执行权后(唤醒后的线程会从上次等待位置,向下执行)就不能再判断
while判断解决唤醒的线程获取执行权后无法判断
notify:只能唤醒任意一个线程,有可能会唤醒本方线程,while+notify会导致死锁
notifyAll:解决了死锁问题