Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向BlockingQueue添加()和take()元素时发生死锁_Java_Multithreading_Threadpool_Executorservice_Blockingqueue - Fatal编程技术网

Java 向BlockingQueue添加()和take()元素时发生死锁

Java 向BlockingQueue添加()和take()元素时发生死锁,java,multithreading,threadpool,executorservice,blockingqueue,Java,Multithreading,Threadpool,Executorservice,Blockingqueue,我正在使用java.util.concurrent包,并使用它的接口/类来了解它们是如何工作的。我创建了一个BlockingQueue实例(ArrayBlockingQueueimlpement)。创建了50个Rannable类型的消费者和50个生产者。然后使用Executors.newFixedThreadPool(4)创建了一个大小为4的线程池,并将我的所有使用者/生产者提交到线程池(ExecutorService)。但最终打印的过程中,我发现它的死锁-ing。谁能解释一下线程安全队列为什么

我正在使用
java.util.concurrent
包,并使用它的接口/类来了解它们是如何工作的。我创建了一个
BlockingQueue
实例(
ArrayBlockingQueue
imlpement)。创建了50个
Rannable
类型的消费者和50个生产者。然后使用
Executors.newFixedThreadPool(4)
创建了一个大小为4的线程池,并将我的所有使用者/生产者提交到
线程池(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++;
        }
    }

}
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();
    }
}
公共类ArrayBlockingQueueConsumer实现可运行{
阻塞队列阻塞队列;
int consumerNumber=0;
公共阵列BlockingQueueConsumer(BlockingQueue BlockingQueue,int consumerNumber){
this.blockingQueue=blockingQueue;
this.consumerNumber=消费者编号;
}
公开募捐{
int i=0;
而
我在消费者/生产者中运行了从0到60的循环,这样当它们分别找不到任何元素或发现队列已满时,就可以抛出异常,具有讽刺意味的是,没有生产者/消费者抛出任何异常

take()
在队列为空时不会引发异常。它会等待元素变为可用

E java.util.concurrent.BlockingQueue.take()抛出InterruptedException

检索并删除此队列的头,在必要时等待,直到某个元素可用

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

take()
在队列为空时不会引发异常。它会等待元素变为可用

E java.util.concurrent.BlockingQueue.take()抛出InterruptedException

检索并删除此队列的头,在必要时等待,直到某个元素可用


这里没有死锁。您的代码在
阻塞队列中为我抛出了一个
IllegalStateException
。add()
调用。这导致队列未按计划填满,最终导致
take()
阻塞,如文档所述。不是死锁


死锁是两个或多个线程无法继续运行的情况,因为它们都在等待对方。

这里没有死锁。您的代码在
BlockingQueue.add()
调用中为我抛出了一个
IllegalStateException
。这导致队列没有按计划填满,最终导致
take()
如文件所述阻止。而不是死锁


死锁是指两个或多个线程无法继续运行的情况,因为它们都在等待对方。

Ohh!是的。这应该是
remove()
。现在工作正常:)谢谢。那么,我应该得出结论说
put(o)
take()
可以创建死锁吗?不,你应该得出结论说
take()
在队列中没有元素时阻塞。@Ashish1269它们不应该阻塞,因为如果
put
等待添加元素,这意味着
take
有一个可用元素要删除,如果
take
等待删除元素,这意味着
put
有可用空间添加元素。@Eran@EJP使用
put(o)
take()
创建了死锁。消费者一直在等待元素添加到队列中,而生产者没有向队列中添加更多的元素。我使用了
put(o)
take()
用于生产者和消费者。@Ashish1269使用put和take是类的全部要点,是一种成熟的模式。给定的代码不会死锁。哦!是的。应该是
remove()
。现在它工作正常:)谢谢。那么,我是否应该得出
put(o)
take()的结论
会造成死锁吗?不,你应该得出结论,
take()
在队列中没有元素时阻塞。@Ashish1269它们不应该阻塞,因为如果
put
等待添加元素,这意味着
take
有一个可用元素要删除,如果
take
等待删除元素,这意味着
put
有可用空间添加元素。@Eran@EJP使用
put(o)
take()
创建了死锁。消费者一直在等待元素添加到队列中,而生产者没有向队列中添加更多的元素。我使用了
put(o)
take()
用于生产者和消费者。@Ashish1269使用put和take是类的全部要点,是一个完善的模式。给定的代码不能死锁。我多次运行上述代码,但没有出现异常。但是在将
take()
替换为
remove()之后
在消费者代码中,当消费者在队列中找不到任何元素(因为队列是空的)时,我得到了
NoTouchElementException
。我运行了一次,得到了异常,坦率地说,我不相信你的说法。异常的发生足以解释
take()中的阻塞
,这里仍然没有任何死锁的证据。我多次运行上述代码,但没有得到异常。但是在消费者代码中将
take()
替换为
remove()
之后,当消费者在队列中找不到任何元素时(因为队列是空的),我会得到
NoSuchElementException
。我运行了一次,得到了异常,坦率地说,我不相信你的说法。异常的发生足以解释
take()
中的阻塞,这里仍然没有任何死锁的证据。我运行了