Javaスレッドの通信学習(マルチスレッド(同期))

分析は、生産者と消費者の古典的なケースをスレッド

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:解决了死锁问题

 

おすすめ

転載: www.cnblogs.com/WarBlog/p/12082961.html