Java多執行緒06:執行緒通訊
阿新 • • 發佈:2021-09-17
Synchronized實現了同步,但不能用實現不同執行緒之間的訊息傳遞
-
wait()方法表示執行緒一直等待,直到其他執行緒通知,與sleep()不同,wait()會釋放鎖
-
notify()方法喚醒一個處於等待的執行緒
-
notifyAll()方法喚醒同一個物件上所有呼叫wait()方法的執行緒,優先順序高的執行緒優先排程
-
只能在Synchronized同步方法和同步塊中使用,否則丟擲異常
管程法
import java.util.ArrayList; public class Hello { public static void main(String[] args) { ArrayList<Integer> arrayList = new ArrayList(); Consumer consumer = new Consumer(arrayList); Producer producer = new Producer(arrayList); //生產消費各十次(注意不能在run()方法裡迴圈十次,不然會生產完所有蘋果再消費) for (int i = 0; i < 10; i++) { new Thread(consumer).start(); new Thread(producer).start(); } } } //定義消費者類 class Consumer implements Runnable{ //定義列表集合放置蘋果 ArrayList<Integer> arrayList; public Consumer(ArrayList arrayList){ this.arrayList = arrayList; } @Override public void run() { //wait()和notify()方法只能在同步塊和同步方法中使用 synchronized (arrayList) { if (arrayList.size() == 0) { System.out.println("蘋果沒有了,需要生產"); try { //wait()方法讓執行緒進入等待,釋放鎖給生產執行緒 //沒有蘋果時消費者進入等待,收到喚醒後才會繼續執行後續的程式碼 arrayList.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //為了避免生產完立即被消費,設定一個延時 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (arrayList.size() != 0){ arrayList.remove(0); System.out.println("消費了一個蘋果,還剩" + arrayList.size() + "個"); } //notify()方法喚醒生產執行緒 arrayList.notify(); } } } //定義生產者類 class Producer implements Runnable{ ArrayList<Integer> arrayList; //定義盤子滿的數量 int max = 10; public Producer(ArrayList arrayList){ this.arrayList = arrayList; } @Override public void run() { synchronized (arrayList) { if (arrayList.size() == max) { System.out.println("盤子滿了,需要消費"); try { arrayList.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } arrayList.add(1); System.out.println("生產了一個蘋果,還剩" + arrayList.size() + "個"); arrayList.notify(); } } }
訊號燈法
import java.util.ArrayList; public class Hello { public static void main(String[] args) { ArrayList<Integer> arrayList = new ArrayList(); //定義一個標誌,為了保證其他執行緒指向的是同一個標誌,需要使用包裝類建立引用物件 Boolean flag = new Boolean(true); Consumer consumer = new Consumer(arrayList, flag); Producer producer = new Producer(arrayList, flag); for (int i = 0; i < 10; i++) { new Thread(consumer).start(); new Thread(producer).start(); } } } //定義消費者類 class Consumer implements Runnable{ ArrayList<Integer> arrayList; Boolean flag = new Boolean(true); public Consumer(ArrayList arrayList, boolean flag){ this.arrayList = arrayList; this.flag = flag; } @Override public void run() { synchronized (arrayList) { if (flag) { try { arrayList.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //當列表長度不為0時,可以消費蘋果 if (arrayList.size() != 0){ arrayList.remove(0); System.out.println("消費了一個蘋果,還剩" + arrayList.size() + "個"); } //反轉標誌位,讓生產者執行緒執行 flag = false; arrayList.notify(); } } } //定義生產者類 class Producer implements Runnable{ ArrayList<Integer> arrayList; Boolean flag = new Boolean(true); public Producer(ArrayList arrayList, boolean flag){ this.arrayList = arrayList; this.flag = flag; } @Override public void run() { synchronized (arrayList) { if (!flag) { try { arrayList.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } arrayList.add(1); System.out.println("生產了一個蘋果,還剩" + arrayList.size() + "個"); flag = true; arrayList.notify(); } } }