想想很容易,寫起來卻並不是很順...磕磕巴巴寫好久有木有。補充回顧不少基礎知識。
參考:
一個生產者和一個消費者的情形。使用synchronized ,wait,notify。由於對於任何一方來說上鎖的一定是對方,最後notify沒什麼問題。但多個消費者會出錯。
一生產者多消費者,不過這個問題的情景生產者的情形有點微妙(等消費完了再生產這點)。
多個生產者多個消費者一種的解決方案。(concurrent的lock,Condition,await,signal)
進階的多生產多消費者解決方案。/**
* 生產者
*
* @author zoe
*
*/
class Productor implements Runnable {
ProductBuffer buf;
String name = "Productor";
Productor(ProductBuffer buf, String name) {
this.buf = buf;
this.name = name;
}
public Product product() {
Product p = new Product();
System.out.println(this.name + "正在生產" + p.thisnum + "號...");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
return p;
}
public void run() {
while (true) {
Product p = product();
try {
buf.add(p);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 消費者
*
* @author zoe
*
*/
class Consumer implements Runnable {
ProductBuffer buf;
String name = "Consumer";
Consumer(ProductBuffer buf, String name) {
this.buf = buf;
this.name = name;
}
public void consume(Product p) {
System.out.println(this.name + "正在消費" + p.thisnum + "號...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
Product p = buf.remove();
consume(p);
Thread.sleep(new Random().nextInt(1000));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 產品
*
* @author zoe
*
*/
class Product {
static int num;
int thisnum = num;
Product() {
num++;
}
}
/**
* 產品緩衝隊列
*
* @author zoe
*
*/
class ProductBuffer {
List<Product> buf = new ArrayList<Product>();
static final int MAX = 10;
// 多生產者消費者關鍵
Lock l = new ReentrantLock();
Condition empty = l.newCondition(); // 消費者的“空”位鎖
Condition full = l.newCondition(); // 生產者的“滿”位鎖
synchronized boolean isFull() {
return buf.size() == MAX;
}
void add(Product p) throws Exception {
l.lock();
if (buf.size() == MAX) {
full.await();
}
buf.add(p);
System.out.println("新生產了一個!buf現有:" + buf.size() + "個\n---------");
empty.signal();
l.unlock();
}
Product remove() throws Exception {
l.lock();
if (buf.size() == 0) {
empty.await();
}
Product p = buf.remove(buf.size() - 1);
System.out.println("剛消費了一個!buf現有:" + buf.size() + "個\n---------");
full.signal();
l.unlock();
return p;
}
運行測試類
public class PAC {
public static void main(String[] args) throws Exception {
ProductBuffer buf = new ProductBuffer();
Productor p1 = new Productor(buf, "生產者a");
Productor p2 = new Productor(buf, "生產者b");
Productor p3 = new Productor(buf, "生產者c");
Consumer c = new Consumer(buf, "消費者1");
Consumer c2 = new Consumer(buf, "消費者2");
new Thread(p1).start();
new Thread(p2).start();
new Thread(p3).start();
new Thread(c).start();
new Thread(c2).start();
}
}