我创建了自己的队列。
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();
}
}
MyProducer.java
import com.conpro.MyQueue;
public class MyProducer implements Runnable {
private final MyQueue queue;
private final int size;
MyProducer(int size,MyQueue q) { this.queue = q; this.size = size; }
@Override
public void run()
{
queue.putTail(String.valueOf(Math.random()));
}
}
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();
}
}
现在我在这里创建了3个制作人。 因此,执行这3行后,队列应该已满。
输出应为:
0
1
2
但它只打印0
。
为什么?
P.S:我还没有写过制作人代码,因为我还没有到达那里。
答案 0 :(得分:1)
由于putTail()
为synchronized
,因此三个线程中只有一个可以输入它。然后该线程永远位于while (q.size() != size)
循环内,而其他两个线程仍然无法进入该方法。
答案 1 :(得分:1)
问题是所有3个主题都进入wait()
但从未通过notifyAll
您的代码存在问题但实际上并不是阻塞队列。这就是我期望阻塞队列的作用:
以下是你的实际所做的事情:
wait()
而不添加wait()
而不添加wait()
而不添加在所有3个添加元素的情况下,元素实际上都没有被添加,我们陷入wait()
因为所有3都进入while
循环,然后什么都没有调用{{1 }}
您在评论中的修正:
notifyAll()
这使它做到了它应该做的事情:如果大小已经达到最大值,则阻止它被告知通过while (q.size() == size)
继续,然后检查大小是否仍然是最大值。对于上面示例中的线程,在收到通知后接收锁(例如步骤6中的线程),它将有机会添加其消息。未收到锁定的线程将在第一个释放锁定后接收锁定,但是大小将再次增加到最大大小,这会导致它再次阻塞。话虽如此,我认为你的方法是一个良好的开端。
您的代码中的一件事是不正确的是您在添加后调用notify
。添加永远不会导致队列大小缩小,但是您要通知notifyAll
方法中等待的所有线程继续。没有理由通知正在等待向队列中添加内容的线程,如果你只是在其中添加一些内容,使其达到最大大小。我认为你的意思是通过等待你的最终putTail
方法的线程做一些事情,这引导我到下一点:
您的下一步将是拥有两个锁定对象,而不是始终使用take
。这样this
方法可以与take
方法分开阻止。在put
方法中使用wait
一个锁,在put
中使用notifyAll
,然后使用另一个锁定take
中的wait
take
中的方法和notifyAll
。这将使您可以单独通知玩家和推杆,而不会像使用put
那样立即通知所有人。
答案 2 :(得分:0)
问题出在MyQueue
类putTail()
方法中。你在wait()
(当前对象)上调用this
,它永远不会被通知。当线程将永远等待。