我无法正确同步此程序,结果也应该在第二个println中为0,因为两个线程每次创建并弹出10000次。 我是否必须以不同的方式进行同步?
import java.util.*;
public class Main00 {
Queue<Integer> q = new PriorityQueue<Integer>();
Random rand = new Random();
public static void main(String[] args) {
new Main00().doStuff();
}
public void doStuff(){
Thread t1=new Thread(new Runnable(){
public void run(){
for(int i=0;i<10000;i++)produce();
}
});
Thread t2=new Thread(new Runnable(){
public void run(){
for(int i=0;i<10000;i++)consume();
}
});
System.out.println("Starting threads, q size is : "+q.size());
t1.start();
t2.start();
try{
t1.join();
t1.join();
}catch(InterruptedException e){}
System.out.println("Ending threads, q size is : "+q.size());
}
synchronized public void produce() {
q.add(rand.nextInt(100));
}
synchronized public void consume() {
q.poll();
}
}
答案 0 :(得分:3)
你没有加入第二个主题:
t1.join();
t1.join();
应该是:
t1.join();
t2.join();
你还使用了poll
,它不会阻止:
检索并删除此队列的头部,如果此队列为空,则返回null。
您可能想要使用PriorityBlockingQueue
:
如果任何线程修改队列,则多个线程不应同时访问PriorityQueue实例。而是使用线程安全的PriorityBlockingQueue类。
检索并删除此队列的头部,必要时等待,直到元素可用为止。
答案 1 :(得分:3)
对poll
的调用不一定会消耗元素。如果队列中没有元素,则只返回null。
为了确保您有效地使用元素,您可以写:
while(q.poll() == null);
此外,根据http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html,类PriorityQueue
不是线程安全的。您应该使用线程安全的PriorityBlockingQueue
类,该类具有阻塞超时的poll
方法。