若干進程經過有限的共享緩衝區交換數據。其中,X個「生產者」進程不斷寫入數據,而Y個「消費者」進程不斷讀出數據;共享緩衝區共有N個;任什麼時候刻只能有一個進程可對公用緩衝池進行操做。ide
咱們已經知道,這樣設計就能夠保證前後順序:對於某一個須要後進行的進程:wait(sth),wait(mutex),signal(mutex),先進行的進程:wait(mutex),signal(mutex),signal(sth)。而本問題也有前後的問題,對於消費者來說,只有先有貨物才能夠消費。對於生產者來說只有有空位才能夠生產。因此須要三個信號量,兩個(full和empty)用來決定前後順序,一個是共享共用緩衝池的標誌。
對於生產者(Producer):wait(empty),wait(mutex),其餘操做,signal(mutex),signal(full)。
對於消費者(Consumer):wait(full),wait(mutex),其餘操做,signal(mutex),signal(empty)。
函數
Java SE 12ui
使用Semaphore類。
void acquire(int permits) :獲取指定數目的資源,若是無可用資源將會一直阻塞等待。至關於wait()。
void release(int permits): 釋放指定數目的資源。至關於signal()。設計
final int N=5;//倉庫容量 private static Integer count = 0;//現有資源數目 final Semaphore empty = new Semaphore(N);//表示空的數目 final Semaphore full = new Semaphore(0);//表示滿的數目 final Semaphore mutex = new Semaphore(1); public static void main(String[] args) { TestG test=new TestG(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); } class Producer implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(3000);//睡眠 } catch (Exception e) { e.printStackTrace(); } try { empty.acquire(1);//wait(empty) mutex.acquire();//wait(mutex) count++; System.out.println(Thread.currentThread().getName()+ "生產者正在生產,目前總共有" + count); } catch (InterruptedException e) { e.printStackTrace(); } finally { mutex.release();//signal(mutex) full.release(1);//signal(full) } } } } class Consumer implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(3000);//睡眠 } catch (Exception e) { e.printStackTrace(); } try { full.acquire(1);//wait(full) mutex.acquire();//wait(mutex) count--; System.out.println(Thread.currentThread().getName()+ "消費者正在消費,目前還剩" + count); } catch (InterruptedException e) { e.printStackTrace(); } finally { mutex.release();//signal(mutex) empty.release(1);//signal(empty) } } } }
由於Semaphore三個信號量都被聲明爲了final因此一旦被聲明再也不會改變,因此若是經過構造函數傳進來N是不行的,由於在這以前Semaphore已經被聲明而且沒法更改。
code
Java SE 12blog
將wait(empty)和wait(mutex)、signal (mutex )和signal (full)、wait (full) 和wait (mutex )、signal (mutex )和signal (empty)結合起來。其實結合起來以後,full和empty就能夠用一個標誌表示了,在這裏我設置爲count表示資源數。用synchronized給mutex加鎖實現同步。進程
private static Integer count=0;//表示現有貨物資源數目 private static String mutex = "mutex";//標誌資源區(倉庫)是否是被佔用 public static void main(String[] args) { Test test=new Test(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Producer()).start(); new Thread(test.new Consumer()).start(); } class Producer implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } synchronized (mutex) {//同步 while (count == 10) {//倉庫滿了 try { mutex.wait();//釋放mutex的鎖 } catch (Exception e) { e.printStackTrace(); } } //生產 count++; System.out.println(Thread.currentThread().getName() + "生產者正在生產,貨物共有"+count); mutex.notifyAll(); } } } } class Consumer implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (mutex) {//同步 while (count == 0) { try { mutex.wait();//釋放mutex } catch (Exception e) { } } count--;//消費 System.out.println(Thread.currentThread().getName() + "消費者正在消費,貨物還剩"+count); mutex.notifyAll(); } } } }