首页 > 解决方案 > Java中使用锁的生产者/消费者线程示例

问题描述

public class ConsumerThreadExample {
public static void main(String[] args) throws InterruptedException {
    Consumer c = new Consumer();
    Thread a = new Thread(()->{while(true)c.consume();});
    Thread b = new Thread(()->{while(true)c.supply();});

    a.start();
    b.start();

    a.join();
    b.join();
    System.out.println("finish");
}
}

class Consumer{
private List<Integer> buffer = new ArrayList<>();
private Lock lock = new ReentrantLock();
private Condition notEnough = lock.newCondition();
private Condition toomuch = lock.newCondition();

public void consume(){
    lock.lock();
    try{
        while(buffer.isEmpty()){notEnough.await();
            System.out.println("consume waiting");}
        System.out.println(buffer);

        for(int i = 0; i < buffer.size(); i++){
            System.out.println("consume "+ buffer.remove(i));

            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("signal supply");
        toomuch.signal();
    }
    catch (Exception e){}
    finally {
        lock.unlock();
    }
}

public void supply(){
    lock.lock();
    try{
        while(!buffer.isEmpty()){toomuch.await();
            System.out.println("supply waiting");}
        System.out.println("Adding");
        buffer.add(1);
        buffer.add(3);
        buffer.add(5);
        System.out.println(buffer);
        System.out.println("signal consume");
        notEnough.signal();
    }
    catch (Exception e){}
    finally {
        lock.unlock();
    }
}
}

大家好,考虑上面的代码,我想练习一个经典的线程示例,即消费者/生产者。所以我希望代码用供应()填充缓冲区,然后向消耗()发出信号以消耗缓冲区。每当缓冲区为空,consume() 再次向 supply() 发出信号,依此类推。但输出看起来有点奇怪。输出:

Adding
[1, 3, 5]
signal consume
consume waiting
[1, 3, 5]
consume 1
consume 5
signal supply
[3]
consume 3
signal supply
supply waiting
Adding
[1, 3, 5]
signal consume
consume waiting
[1, 3, 5]
consume 1
consume 5
signal supply
[3]
consume 3
signal supply
supply waiting
Adding
[1, 3, 5]

为什么它消耗 1 和 5 然后信号供应()?3在哪里?为什么它不在 1,3,5 的顺序中?

标签: javamultithreadingasync-awaitlocking

解决方案


在第一次迭代中

i = 0
buffer = [1, 3, 5]

然后你删除 1。在第二次迭代中

i = 1
buffer = [3, 5]

然后删除 5。然后退出循环,因为 i 现在大于长度。


推荐阅读