java多執行緒之生產者消費者經典問題
阿新 • • 發佈:2019-02-08
看過 http://blog.csdn.net/thinkpadshi/article/details/8163751 下面的評論說: 感覺你的程式碼有問題啊,兩個run()方法裡面的列印語句的執行先後問題,假設開始在消費時index==0;這時wait()了,生產者便搶到鎖,index+1;同時叫醒消費者,這個時候要是消費者先於生產者的列印了一條消費了0個,之後再列印生產了0個怎麼辦??!,我執行後也發現這樣的問題,如果把100毫秒改為10毫秒,會有更多這樣的情況產生.
於是自己改了下博主的程式碼:
我就只是改動了 輸出的位置 這是由於System.out.println()函式不是立刻就列印的,它要呼叫其他的函式來完成輸出,所以System.out.println("生產了" + p[index]); 還有 System.out.println("消費了" + p[index]);具體的列印時間就不確定了. 但是如果把輸出列印放在同步程式碼塊裡面,就不會有這樣的問題.因為會完成列印之後才會執行下一步.package deadLockThread; public class SX { public static void main(String[] args) { ProductList pl = new ProductList(); Factory f = new Factory(pl); Consumer c = new Consumer(pl); Thread t1 = new Thread(f); Thread t2 = new Thread(c); t1.start(); t2.start(); } } class Product { private int id; Product(int id) { this.id = id; } @Override public String toString() { return "Product [id=" + id + "]"; } } class ProductList { int index = 0; private Product[] p = new Product[6]; public synchronized void push(Product pr) { while (index == p.length) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); p[index] = pr; <span style="color:#ff0000;">System.out.println("生產了" + p[index]);</span> index++; } public synchronized Product pop() { while (index == 0) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); index--; <span style="color:#ff0000;">System.out.println("消費了" + p[index]);</span> return p[index]; } } class Factory implements Runnable { private ProductList pl = null; Factory(ProductList pl) { this.pl = pl; } @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 20; i++) { Product p = new Product(i); pl.push(p); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } class Consumer implements Runnable { private ProductList pl = null; Consumer(ProductList pl) { this.pl = pl; } @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 20; i++) { Product p = pl.pop(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }