1synchronized + wait()+ notifyAllで実現
アイデア:プロデューサーが最大数に達したら、プロデューサースレッドにブロックと待機を待機させます。それ以外の場合は、プロデュースを続行し、同時にコンシューマーに消費するように通知します。
コンシューマーが0を消費する場合、コンシューマースレッドをブロックして待機するまで待機させます。それ以外の場合は消費を継続し、同時にプロデューサーに生成を通知します。
パブリッククラスContainer1 <T> { 最終プライベートLinkedList <T>リスト=新しいLinkedList <T>(); final private int MAX = 10; //最多10要素privateint count = 0; public synchronized void put(T t){ while(lists.size()== MAX){ try { this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } } lists.add(t); ++カウント; this.notifyAll(); //消費消费者ワイヤー程の行消费 } public synchronized T get(){ T t = null; while(lists.size()== 0){ try { this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } } t = lists.removeFirst(); カウント - ; this.notifyAll(); //通知生生産者進行行生生産returnt ; } public static void main(String [] args){ Container1 <String> c = new Container1 <>(); //启PIN消费者線程 for(int i = 0; i <10; i ++){ new Thread(()-> { for(int j = 0; j <5; j ++){ System.out.println(Thread。 currentThread()。getName()+ "get =" + c.get()); } }、 "c" + i).start(); } 試してください{ TimeUnit.SECONDS.sleep(2); } catch(InterruptedException e){ e.printStackTrace(); } // (int i = 0;のプロデューサースレッドを開始しますi <2; i ++){ new Thread(()-> { for(int j = 0; j <25; j ++){ c.put(Thread.currentThread()。getName()+ "set =" + j) ; } }、 "p" + i).start(); } } } この実装には問題があります。プロデューサースレッドがnotifyAll通知を呼び出すと、プロデューサースレッドに通知する場合があり、コンシューマースレッドはnotifyAll通知を呼び出します。その時点でコンシューマスレッドに通知することが可能であるため、改善することができます。この問題を解決するために、以下の2番目の方法を使用します。
2ロックとコンディションを使用して
ロック処理を実行するときのインターフェースもあります。条件。このインターフェースは、ユーザーがロックのオブジェクトを作成するために作成できます。
Conditionの機能は、ロックをより正確に制御することです。
await()のメソッドの条件があると同等ウエイト()のメソッドオブジェクト、信号()のメソッド条件であると同等の通知()のメソッドオブジェクト、及びsignalAll()のメソッド条件であると同等(のnotifyAll )オブジェクトのメソッド。
違いは、Objectのwait()、notify()、notifyAll() メソッドが「同期ロック」(同期キーワード)と組み合わせて使用されるのに対し、Conditionは「相互排他ロック/共有ロック」と組み合わせて使用する必要があることです。。
条件を使用して、2つの待機キューを使用して、それぞれプロデューサーキューとコンシューマーキューを実装します
パブリッククラスContainer2 <T> { 最終プライベートLinkedList <T>リスト=新しいLinkedList <>(); final private int MAX = 10; //最多10要素privateint count = 0; プライベートロックロック= new ReentrantLock(); プライベート条件プロデューサー= lock.newCondition(); プライベート条件consumber = lock.newCondition(); public void put(T t){ try { lock.lock(); while(lists.size()== MAX){ producer.await(); } lists.add(t); ++カウント; consumber.signalAll(); //消費消费者スレッド程の行消费 } catch(InterruptedException e){ e.printStackTrace(); } 最後に { 施錠開錠(); } } public T get(){ T t = null; { lock.lock();を試してください。 while(lists.size()== 0){ consumber.await(); } t = Lists.removeFirst(); カウント - ; producer.signalAll(); //生産生生産者追跡生プログラム } catch(InterruptedException e){ e.printStackTrace(); }最後に{ lock.unlock(); } return t; } public static void main(String [] args){ Container2 c = new Container2(); for(int i = 0; i <10; i ++){ new Thread(()-> { for(int j = 0; j <5; j ++){ System.out.println(Thread.currentThread()。getName()+ "get =" + c.get()); } }、 "c" + i).start(); } try { TimeUnit.SECONDS.sleep(2); } catch(InterruptedException e){ e.printStackTrace(); } //启PIN生生産者ワイヤー程 for(int i = 0; i <2; i ++){ new Thread(()-> { for(int j = 0; j <25; j ++){ c.put(Thread.currentThread ().getName()+ "set =" + j); }、 "p" + i).start(); } }