多生產者/消費者
多個生產者和消費者,同時限制生產者和消費者的數量
類Semaphore提供了限制併發線程數的功能,此功能在默認的synchronized中是不提供的。
代碼
/**
* 實現生產者消費者模式
* 限制生產者與消費者的數量
*/
package com.lhc.concurrent.semaphore.repast;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class RepastService {
/**
* 初始化生產者和消費者兩個信號量
*/
volatile private Semaphore cook = new Semaphore(10);
volatile private Semaphore diner = new Semaphore(5);
/**
* 初始化兩個Condition
*/
volatile private ReentrantLock lock = new ReentrantLock();
volatile private Condition setCondition = lock.newCondition();
volatile private Condition getCondition = lock.newCondition();
/**
* 初始化一個容器
*/
volatile private Object[] producePosition = new Object[4];
/**
* 判斷容器是否爲空
* @return
*/
public boolean isEmpty() {
for (int i = 0; i < producePosition.length; i++) {
if (producePosition[i] != null) {
return false;
}
}
return true;
}
/**
* 判斷容器是否已滿
* @return
*/
public boolean isFull() {
for (int i = 0; i < producePosition.length; i++) {
if (producePosition[i] == null) {
return false;
}
}
return true;
}
/**
* 在容器填一次數據
* 當容器已滿,就等待
* 等到被通知再繼續填充
* 填充一次以後,通知未空
*/
public void set() {
try {
cook.acquire();
lock.lock();
while (isFull()) {
setCondition.await();
}
for (int i = 0; i < producePosition.length; i++) {
if (producePosition[i] == null) {
producePosition[i] = "food";
System.out.println(Thread.currentThread().getName() + " cook " + producePosition[i] + i);
break;
}
}
getCondition.signalAll();
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
cook.release();
}
}
/**
* 在容器取一次數據
* 當容器已空時,就等待
* 等到被通知再繼續取
* 取一次以後,通知未滿
*/
public void get() {
try {
diner.acquire();
lock.lock();
while (isEmpty()) {
getCondition.await();
}
for (int i = 0; i < producePosition.length; i++) {
if (producePosition[i] != null) {
System.out.println(Thread.currentThread().getName() + " eat food" + i);
producePosition[i] = null;
break;
}
}
setCondition.signalAll();
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
diner.release();
}
}
}
測試類
package com.lhc.concurrent.semaphore.repast;
public class CookThread extends Thread {
private RepastService repastService;
public CookThread(RepastService repastService) {
this.repastService = repastService;
}
@Override
public void run() {
repastService.set();
}
public static void main(String[] args) throws InterruptedException{
RepastService repastService = new RepastService();
CookThread[] cookThreads = new CookThread[20];
EatThread[] eatThreads = new EatThread[20];
for (int i = 0; i < 20; i++){
cookThreads[i] = new CookThread(repastService);
eatThreads[i] = new EatThread(repastService);
}
Thread.sleep(2000);
for (int i = 0; i < 20; i++){
cookThreads[i].start();
eatThreads[i].start();
}
}
}
package com.lhc.concurrent.semaphore.repast;
public class EatThread extends Thread {
private RepastService repastService;
public EatThread(RepastService repastService) {
this.repastService = repastService;
}
@Override
public void run() {
repastService.get();
}
}
測試結果
Thread-0 cook food0
Thread-11 eat food0
Thread-8 cook food0
Thread-4 cook food1
Thread-2 cook food2
Thread-3 eat food0
Thread-16 cook food0
Thread-18 cook food3
Thread-5 eat food0
Thread-26 cook food0
Thread-1 eat food0
Thread-28 cook food0
Thread-15 eat food0
Thread-6 cook food0
Thread-9 eat food0
Thread-19 eat food1
Thread-7 eat food2
Thread-38 cook food0
Thread-12 cook food1
Thread-14 cook food2
Thread-13 eat food0
Thread-29 eat food1
Thread-30 cook food0
Thread-24 cook food1
Thread-17 eat food0
Thread-25 eat food1
Thread-36 cook food0
Thread-21 eat food0
Thread-23 eat food2
Thread-37 eat food3
Thread-20 cook food0
Thread-32 cook food1
Thread-22 cook food2
Thread-34 cook food3
Thread-31 eat food0
Thread-27 eat food1
Thread-10 cook food0
Thread-33 eat food0
Thread-35 eat food2
Thread-39 eat food3