對這個問題更深一點理解是,每一個線程都在競爭這個類的實例的monitor對象。
java會為每個object對象分配一個monitor,當某個對象的同步方法(synchronized methods )被多個線程調用時,該對象的monitor將負責處理這些訪問的並發獨占要求。
任何時刻,對一個指定object對象的某同步方法只能由一個線程來調用。java對象的monitor是跟隨object實例來使用的,而不是跟隨程序代碼。兩個線程可以同時執行相同的同步方法,比如:一個類的同步方法是xMethod(),有a,b兩個對象實例,一個線程執行a.xMethod(),另一個線程執行b.xMethod(). 互不沖突。下面是單生產者單消費者的實例

1 /* 2 * 生產者消費者 3 * 分類: 4 * 單生產者單消費者 5 * 多生產者的消費者 6 * 7 * 8 * 單生產者單消費者: 9 * 兩個線程:生產線程,消費線程 10 * 兩個任務:生產任務,消費任務 11 * 一份數據 12 */ 13 public class Demo4 { 14 public static void main(String[] args) { 15 //1.准備數據 16 Product product = new Product(); 17 //2.創建生產消費任務 18 Producer producer = new Producer(product); 19 Consumer consumer = new Consumer(product); 20 //3.創建生產消費線程 21 Thread thread1 = new Thread(producer); 22 Thread thread2 = new Thread(consumer); 23 //4.開啟線程 24 thread1.start(); 25 thread2.start(); 26 } 27 } 28 29 //數據類 30 class Product{ 31 String name; 32 double price; 33 int count; 34 35 //標識 36 boolean flag; 37 38 //准備生產 39 public synchronized void setProduce(String name,double price) { 40 if (flag == true) { 41 try { 42 wait(); 43 } catch (InterruptedException e) { 44 // TODO Auto-generated catch block 45 e.printStackTrace(); 46 } 47 } 48 49 this.name = name; 50 this.price = price; 51 52 System.out.println(Thread.currentThread().getName()+" 生產了:"+name+" 產品的數量:"+count+" 產品的價格:"+price); 53 54 count++; 55 56 flag = !flag; 57 58 //喚醒消費線程 59 notify(); 60 } 61 //准備消費 62 public synchronized void consume() { 63 if (flag == false) { 64 try { 65 wait(); 66 } catch (InterruptedException e) { 67 // TODO Auto-generated catch block 68 e.printStackTrace(); 69 } 70 } 71 72 System.out.println(Thread.currentThread().getName()+" 消費了:"+name+" 產品的數量:"+count+" 產品的價格:"+price); 73 74 flag = !flag; 75 76 //喚醒生產線程 77 notify(); 78 } 79 } 80 //生產任務 81 class Producer implements Runnable{ 82 Product product; 83 84 public Producer(Product product) { 85 super(); 86 this.product = product; 87 } 88 89 public void run() { 90 while (true) { 91 product.setProduce("bingbing", 10); 92 } 93 } 94 } 95 //消費任務 96 97 class Consumer implements Runnable{ 98 Product product; 99 100 public Consumer(Product product) { 101 super(); 102 this.product = product; 103 } 104 105 public void run() { 106 while (true) { 107 product.consume(); 108 } 109 } 110 }
多生產者多消費者:
* 兩個生產線程,兩個消費線程
* 兩個任務:生產任務,消費任務
* 一份數據
*
* 生產任務與消費任務共用一個數據--產品類
*
* 要求:最終也要實現一次生產一次消費
*
*錯誤描述:當有兩個生產線程,兩個消費線程同時存在的時候,有可能出現生產一次,消費多次或者生產多次消費一次的情況.
*原因:當線程被重新喚醒之后,沒有判斷標記,直接執行了下面的代碼
*
*解決辦法:將標記處的if改成while
*
*問題描述:繼續運行程序,會出現死鎖的情況(4個線程同時處於等待狀態)
*原因:喚醒的是本方的線程,最后導致所有的線程都處於等待狀態.
*
*解決辦法:將notify改成notifyAll.保證將對方的線程喚醒
*
*死鎖:出現的情況有兩種
*1.所有的線程處於等待狀態
*2.鎖之間進行嵌套調用
*
*/
public class Demo5 { public static void main(String[] args) { //1.准備數據 Product1 product = new Product1(); //2.創建生產消費任務 Producer1 producer = new Producer1(product); Consumer1 consumer = new Consumer1(product); //3.創建生產消費線程 Thread thread0 = new Thread(producer); Thread thread1 = new Thread(producer); Thread thread2 = new Thread(consumer); Thread thread3 = new Thread(consumer); //4.開啟線程 thread0.start(); thread1.start(); thread2.start(); thread3.start(); } } //數據類 class Product1{ String name; double price; int count; //標識 boolean flag; //准備生產 public synchronized void setProduce(String name,double price) { while (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name = name; this.price = price; System.out.println(Thread.currentThread().getName()+" 生產了:"+name+" 產品的數量:"+count+" 產品的價格:"+price); count++; flag = !flag; //喚醒消費線程 //notify(); notifyAll(); } //准備消費 public synchronized void consume() { while (flag == false) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 消費了:"+name+" 產品的數量:"+count+" 產品的價格:"+price); flag = !flag; //喚醒生產線程 //notify(); notifyAll(); } } //生產任務 class Producer1 implements Runnable{ Product1 product; public Producer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.setProduce("bingbing", 10); } } } //消費任務 class Consumer1 implements Runnable{ Product1 product; public Consumer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.consume(); } } }