java - 将 add() 和 take() 元素添加到 BlockingQueue 时死锁

标签 java multithreading threadpool executorservice blockingqueue

我正在玩 java.util.concurrent 包并使用它的接口(interface)/类来了解它们是如何工作的。我创建了一个 BlockingQueue 实例(ArrayBlockingQueue imlpementation)。并创建了 50 个 Rannable 类型的消费者和 50 个生产者。然后使用 Executors.newFixedThreadPool(4) 创建一个大小为 4 的线程池,并将我所有的消费者/生产者提交给 threadPool (ExecutorService)。但最终打印过程我认为它是死锁-ing。谁能解释为什么线程安全队列会死锁!?下面是我的代码:

消费者:

public class ArrayBlockingQueueConsumer implements Runnable{

    BlockingQueue<Integer> blockingQueue;
    int consumerNumber = 0;

    public ArrayBlockingQueueConsumer(BlockingQueue<Integer> blockingQueue, int consumerNumber) {
        this.blockingQueue = blockingQueue;
        this.consumerNumber = consumerNumber;
    }

    public void run() {
        int i = 0;
        while(i<60) {
            System.out.printf("Consumer %d going take %d from blocking queue\n", consumerNumber, i);
            try {
                int x = blockingQueue.take();
                System.out.println("The number " + x + "is taken from the queue.");
            } catch (InterruptedException e) {
                System.out.printf("Consumer %d interrupted while adding %d to blocking queue\n", consumerNumber, i);
                e.printStackTrace();
            }
            i++;
        }
    }
}

制作人:

public class ArrayBlockingQueueProducer implements Runnable{

    BlockingQueue<Integer> blockingQueue;
    int producerNumber = 0;

    public ArrayBlockingQueueProducer(BlockingQueue<Integer> blockingQueue, int producerNumber) {
        this.blockingQueue = blockingQueue;
        this.producerNumber = producerNumber;
    }

    public void run() {
        int i = 0;
        while(i<60) {
            System.out.printf("Consumer %d going to add %d to blocking queue\n", producerNumber, i);
            blockingQueue.add(i);
            System.out.printf("Consumer %d added %d to blocking queue\n", producerNumber, i);
            i++;
        }
    }

}

执行器类(main()方法类):

public class BlockingQueueExecutor {

    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(50);

        ArrayBlockingQueueConsumer[] consumers = new ArrayBlockingQueueConsumer[200];
        ArrayBlockingQueueProducer[] producers = new ArrayBlockingQueueProducer[200];

        System.out.println("Hello hello :D");

        for (int i = 0; i < 200; i++) {
            consumers[i] = new ArrayBlockingQueueConsumer(blockingQueue, i+1);
            producers[i] = new ArrayBlockingQueueProducer(blockingQueue, i+1);
        }

        ExecutorService threadPool = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 200; i++) {
            threadPool.execute(consumers[i]);
            threadPool.execute(producers[i]);
        }

        threadPool.shutdown();
    }
}

我在消费者/生产者中运行了从 0 到 60 的循环,这样他们就可以在找不到任何元素或发现队列已满时抛出异常,具有讽刺意味的是,没有一个生产者/消费者抛出任何异常。

最佳答案

I ran the loops in consumers/producers from 0 to 60 so that they can throw exception when they don't find any element or find queue full respectively, ironically none of the producers/consumers threw any exception.

take() 在队列为空时不会抛出异常。它一直等到元素可用。

E java.util.concurrent.BlockingQueue.take() throws InterruptedException

Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

关于java - 将 add() 和 take() 元素添加到 BlockingQueue 时死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46871168/

相关文章:

multithreading - 从另一个线程WinRT中的ViewModel更新INotifyPropertyChanged-property

c++ - 使用 g++ 编译多线程代码(-Wl,--no-as-needed 不工作)

java - 多线程 Java 正则表达式

c# - Task.Factory.StartNew() 是否保证至少创建一个新线程?

java - 具有抽象泛型和集合的 JPA 单表继承

java - Java 中的 JSON 数组

multithreading - 使用 OpenCV 时的 OpenMP 和显式线程互操作性

java - Tomcat 7 Servlet 产生一个线程

java - winio64.dll 中有哪些方法以及如何使用它们

java - Eclipselink 是否在 Apache Felix 下使用(动态)字节码编织?