日期:2014-05-20  浏览次数:20725 次

java 多线程实现生产者模型问题

public class Baskert {

private List<String> list = new ArrayList<String>();

private Lock lock = new ReentrantLock();

private Condition setter = lock.newCondition(); //篮子为满的条件

private Condition getter = lock.newCondition(); //篮子为空的条件

public void addApple() throws InterruptedException{
try{
lock.lock();
while(list.size()>=5){
System.out.println(Thread.currentThread().getName()+"--挂起");
setter.await();
}
list.add("红富士");
System.out.println(Thread.currentThread().getName()+"放了一个红富士==="+list.size());
System.out.println("释放2,3");
getter.signalAll();
}finally{
lock.unlock();
}
}

public void removeApple() throws InterruptedException{
try{
lock.lock();
while(list.size()<=0){
System.out.println(Thread.currentThread().getName()+"--挂起");
getter.await();
}
list.remove(0);
System.out.println(Thread.currentThread().getName()+"拿了一个苹果==="+list.size());
System.out.println("释放0,1");
setter.signalAll();
}finally{
lock.unlock();
}
}

public static void main(String[] args){
final Baskert baskert = new Baskert();
new Thread(new Runnable() {

public void run() {
try {
while(true){
baskert.addApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
new Thread(new Runnable() {

public void run() {
try {
while(true){
baskert.addApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
new Thread(new Runnable() {

public void run() {
try {
while(true){
baskert.removeApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
new Thread(new Runnable() {

public void run() {
try {
while(true){
baskert.removeApple();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
}

}


结果是:
Thread-1放了一个红富士===1
释放2,3
Thread-1放了一个红富士===2
释放2,3
Thread-1放了一个红富士===3
释放2,3
Thread-1放了一个红富士===4
释放2,3
Thread-1放了一个红富士===5
释放2,3
Thread-1--挂起
Thread-0--挂起
Thread-3拿了一个苹果===4
释放0,1
Thread-3拿了一个苹果===3
释放0,1
Thread-3拿了一个苹果===2
释放0,1
Thread-3拿了一个苹果===1
释放0,1
Thread-3拿了一个苹果===0
释放0,1
Thread-3--挂起
Thread-2--挂起
Thread-1放了一个红富士===1
释放2,3
Thread-1放了一个红富士===2

可见只有一个线程把篮子放满或者拿空,挂起之后另一个线程才会操作。
而我觉得结果应该是 只要篮子不满或者不空,放苹果线程和取苹果线程应该是同时进行的,请高手指点为什么会这样
------解决方案--------------------
你的代码没有问题,我重新组织了一下,以便更好地观察结果。

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 多线程生产者-消费者示例
 */
public class Basket {

    public static final int BASKET_CAPACITY = 5;

    private List<String> list = new ArrayList<>();

    private Lock lock = new ReentrantLock();

    private Condition setter = lock.newCondition(); //篮子为满的条件

    private Condition getter = lock.newCondition(); //篮子为空的条件

    // 放入苹果
    public void addApple() throws InterruptedException {
        try {
            lock.lock();
            while (list.size() >= BASKET_CAPACITY) {
                outputThreadMessage("篮子已满,等待取出", false);
                setter.await();
            }
            list.add("红富士");
            outputThreadMessage("放入苹果: 篮子里还有" + list.size(), false);

            getter.signalAll();
        } finally {
            lock.unlock();
        }