我有以下内容:
public class ProducerConsumer {
private BlockingQueue<Integer> q;
private Random rnd;
private boolean run;
public ProducerConsumer(){
rnd = new Random();
q = new ArrayBlockingQueue<>(10);
run = true;
}
// high leve - with ArrayBlockingQueue
public void QProducer() throws InterruptedException{
int i;
while(run){
i = rnd.nextInt(100);
q.put(i);
System.out.println(i +" Added. Size is: "+ q.size());
}
}
public void QConsumer() throws InterruptedException{
int i;
while(run){
Thread.sleep(100);
if (rnd.nextInt(10) == 0) {
i = q.take();
System.out.println(i + " Taken. Size is: "+ q.size());
}
}
}
public void changeRun(){
run = false;
}
}
<小时/>
public static void main(String[] args) throws InterruptedException {
// Producer Consumer
final ProducerConsumer pc = new ProducerConsumer();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
pc.QProducer();
} catch (InterruptedException ex) {
Logger.getLogger(Threading.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
pc.QConsumer();
} catch (InterruptedException ex) {
Logger.getLogger(Threading.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
t1.start();
t2.start();
Scanner scn = new Scanner(System.in);
scn.nextLine();
pc.changeRun();
t1.join();
t2.join();
}
输出:
20 Added. Size is: 1
8 Added. Size is: 2
71 Added. Size is: 3
72 Added. Size is: 4
61 Added. Size is: 5
97 Added. Size is: 6
6 Added. Size is: 7
64 Added. Size is: 8
58 Added. Size is: 9
27 Added. Size is: 10
20 Taken. Size is: 10 *
93 Added. Size is: 10
8 Taken. Size is: 9
95 Added. Size is: 10
71 Taken. Size is: 10 *
70 Added. Size is: 10
72 Taken. Size is: 10 *
85 Added. Size is: 10
61 Taken. Size is: 9
43 Added. Size is: 10
64 Added. Size is: 10 **
...
我想知道怎么会有数字被取走,但大小却保持不变(*), 以及如何在队列满后添加值( ** )。 AFAIU,BlockingQueue 是同步的,如果队列为空,则等待添加值,如果已满,则等待删除。 预先感谢您。
最佳答案
由于多线程,put()
和它后面的 println/size()
以及 take()
和它后面的 println/size()
可以交错。因此,size()
返回的值在打印时可能已经过时。例如
1a. Add (size = 10)
1b. Print size 10
2a. Take (size = 9)
3a. Add (size = 10)
2b. Print size 10
3b. Print size 10
关于java - 2 个线程修改共享 BlockingQueue 的意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13113460/