轉載請註明出處:http://blog.csdn.net/sunyujia/
論壇上的網友提出的問題,每生產3個只能消費2個,感覺不是很難於是動手操之,為了省事
在原來的http://blog.csdn.net/sunyujia/archive/2008/05/02/2362015.aspx 基礎上修改的。
唯一的痛點在於生產3個的線程不是同一線程。消費2個的線程不是同一線程。就是說不能是一個線程連續生產3個,一個線程連續消費2個,如果是一個線程連續生產的話,程式就沒意思了。
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- /**
- * 有趣的生產者消費者問題
- * 每產生3個消費2個
- * @author: sunyujia
- * @blog: http://blog.csdn.net/sunyujia/
- * @mail: sunyujia@sunyujia@yahoo.cn
- */
- public class ExecutorServiceTest {
- private static int produceCount = 0;
- private static int consumeCount = 0;
- private static Object produceLock = new Object();
- private static Object consumeLock = new Object();
- public static void main(String[] args) {
- final List tasks = new ArrayList();
- System.out.println("MyBlog: http://blog.csdn.net/"+"sunyujia/");
- final ExecutorService exec = Executors.newCachedThreadPool();
- for (int i = 0; i < 10; i++) {//10個生產者
- exec.execute(new Runnable() {
- public void run() {
- while (!Thread.interrupted()) {
- try {
- synchronized (consumeLock) {
- if (produceCount >= 3)
- consumeLock.wait();
- }
- synchronized (produceLock) {
- if (produceCount < 3) {
- tasks.add(new Object());// 生產
- System.out.println(Thread.currentThread().getName()+"生產任務 還剩:" + tasks.size());
- produceCount++;
- if (produceCount >= 3) {
- consumeCount = 2;// 提示只能消費2個
- System.out.println("生產者友情提示現在庫存"
- + tasks.size());
- produceLock.notifyAll();
- }
- Thread.yield();
- }
- }
- Thread.sleep(600);// 讓程式執行慢點以便觀察
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- });
- }
- for (int i = 0; i < 20; i++) {//20個消費者
- exec.execute(new Runnable() {
- public void run() {
- while (!Thread.interrupted()) {
- try {
- synchronized (produceLock) {
- if (consumeCount <= 0)
- produceLock.wait();
- }
- synchronized (consumeLock) {
- if (consumeCount > 0) {
- tasks.remove(0);// 消費
- System.out.println(Thread.currentThread().getName()+"處理任務 還剩:"
- + tasks.size());
- consumeCount--;
- if (consumeCount <= 0) {
- produceCount = 0;// 要求再產生3個
- System.out.println("消費者友情提示現在庫存"
- + tasks.size());
- consumeLock.notifyAll();
- }
- }
- }
- Thread.sleep(600);// 讓程式執行慢點以便觀察
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- });
- }
- exec.shutdown();
- }
- }
執行結果如下:
pool-1-thread-1生產任務 還剩:1
pool-1-thread-2生產任務 還剩:2
pool-1-thread-4生產任務 還剩:3
生產者友情提示現在庫存3
pool-1-thread-11處理任務 還剩:2
pool-1-thread-12處理任務 還剩:1
消費者友情提示現在庫存1
pool-1-thread-5生產任務 還剩:2
pool-1-thread-6生產任務 還剩:3
pool-1-thread-7生產任務 還剩:4
生產者友情提示現在庫存4
pool-1-thread-14處理任務 還剩:3
pool-1-thread-16處理任務 還剩:2
消費者友情提示現在庫存2
pool-1-thread-3生產任務 還剩:3
pool-1-thread-2生產任務 還剩:4
pool-1-thread-4生產任務 還剩:5
生產者友情提示現在庫存5