Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.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

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 为什么我的制作人-消费者计划被阻止?_Java_Multithreading_Producer Consumer - Fatal编程技术网

Java 为什么我的制作人-消费者计划被阻止?

Java 为什么我的制作人-消费者计划被阻止?,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,我已经创建了自己的队列 Queue.java public class MyQueue { private int size; private Queue<String> q; public MyQueue(int size ,Queue<String> queue) { this.size = size; this.q = queue; } //getter and setter pub

我已经创建了自己的队列

Queue.java

public class MyQueue {

    private int size;

    private Queue<String> q;

    public MyQueue(int size ,Queue<String> queue) {
    this.size = size;
    this.q = queue;

    }

    //getter and setter    

    public synchronized void putTail(String s) {

System.out.println(this.size); // It should print 0, 1,2

          while (q.size() != size) {

             try {
                wait();
             }
             catch (InterruptedException e) {
             }
          }
          Date d = new Date();

          q.add(d.toString());

          notifyAll();

       }

}
MyTest.java

public class MyTest {

    public static void main(String[] args) {

        Queue q = new PriorityQueue<String>();
        MyQueue mq = new MyQueue(3,q);

         MyProducer p = new MyProducer(3,mq);
         MyProducer p1 = new MyProducer(3,mq);
         MyProducer p2 = new MyProducer(3,mq);
         new Thread(p).start();
         new Thread(p1).start();
         new Thread(p2).start();

    }

}
但它只打印
0

为什么?


注:我只写了生产者代码,因为我还没有到达那里。

因为
putTail()
同步的
,三个线程中只有一个可以进入它。然后,该线程永远位于
while(q.size()!=size)
循环中,而其他两个线程仍然无法进入该方法。

问题在于
MyQueue
类的
putTail()
方法。在
这个
(当前对象)上调用
wait()
,它永远不会被通知。然后线程将永远等待

问题是,所有3个线程都进入了
wait()
,但从未通过
notifyAll

您的代码有一个问题,它并没有真正成为阻塞队列。我希望阻塞队列可以执行以下操作:

  • 队列的最大大小为3,从没有元素开始
  • 从制作人那里得到一些东西,大小还不是3,添加它,不要阻塞
  • 从制作人那里得到其他东西,大小还不是3,添加它,不要阻止
  • 从制作人那里得到其他东西,大小还不是3,添加它,不要阻止
  • 从制作人那里得到其他东西,尺寸现在是3,直到有东西被拿走为止
  • 从制作人那里得到其他东西,尺寸仍然是3,直到有东西被拿走为止
  • 一个使用者从队列中取出,通知(5)和(6)中的线程,第一个被调度的线程获得足够长的锁以添加他的元素,另一个被强制再次阻塞,直到另一个使用者从队列中取出
  • 以下是您的实际操作,如书面所示:

  • 队列的最大大小为3,从没有元素开始
  • 从制作人处获取内容,大小尚未达到3,在
    wait()
    上阻止,但不添加内容
  • 从制作人处获取内容,大小尚未达到3,在
    wait()
    上阻止,但不添加内容
  • 从制作人处获取内容,大小尚未达到3,在
    wait()
    上阻止,但不添加内容
  • 在添加元素的所有3种情况下,元素实际上并没有被添加,我们被困在
    wait()
    ,因为所有3种情况都在
    循环时进入
    ,然后没有任何东西调用
    notifyAll()

    您在评论中的修复:

    while (q.size() == size)
    
    这使它可以执行它应该执行的操作:如果大小已经达到最大值,则阻塞,直到通过
    通知通知它继续,然后检查大小是否仍然是最大值。对于上面示例中在收到通知后接收锁的线程(例如步骤6中的线程),它将有机会添加其消息。未接收锁的线程将在第一个线程释放锁后接收锁,但大小将再次增加到最大大小,从而导致它再次阻塞。尽管如此,我认为你的方法是一个良好的开端

    代码中有一点是不正确的,那就是在添加后调用了
    notifyAll
    。添加不会导致队列大小缩小,但您会通知在
    putTail
    方法中等待的所有线程继续。如果您只是在队列中添加了使其达到最大大小的内容,那么没有理由通知正在等待向队列添加内容的线程。我想你的意思是让notify对等待你最终的
    take
    方法的线程做些什么,这就引出了我的下一点:


    下一步是使用两个锁定对象,而不是总是使用
    this
    。这样,
    take
    方法可以与
    put
    方法分开进行阻塞。在
    put
    方法中使用一个锁来
    wait
    ,在
    take
    中使用
    notifyAll
    ,然后在
    take
    方法中使用另一个锁来
    wait
    ,在
    put
    中使用
    notifyAll
    。这将使您可以单独通知接球手和推杆手,而无需像使用
    此选项那样立即通知所有接球手和推杆手。notifyAll

    我解决消费者-生产者问题的方向正确吗?我能改变什么?@思考者:TBH,我不认为你是。以下可能是一个好的开始:我可以在putTail方法中更改什么?这真的正确吗
    wait()
    上释放监视器,并允许其他对象在其上同步,因此我认为实际发生的情况是所有三个线程最终都在等待
    wait()
    调用。我尝试了调试。我猜所有3个线程都卡在wait()上。我应该怎么做?您是否出于学习原因实施了自己的
    队列
    ?您可以使用JDK.Yes中已有的
    BlockingQueue
    实现之一。只是为了学习。我尝试过使用BlockingQueue。我想测试“等待”和“通知”。这就是为什么我创建了自己的队列
    BlockingQueue
    会为你做这件事,因为
    get
    方法会一直阻止,直到
    队列中有东西出现为止。我知道这就是为什么我创建了自己的队列。哦-你及时删除了灾难性的“静态”建议-即将否决投票!
    
    0
    1
    2
    
    while (q.size() == size)