那么,如果你只想要最近生成的字符串,那么你根本不需要一个队列 - 你需要的只是一个字符串引用:生产者设置它,消费者读取它。如果消费者花了很长时间阅读它,生产者重新设置它......那又如何?
设置和读取参考是原子的。唯一的问题是,如果您希望消费者以某种方式被通知有可用的字符串。但即使如此......如果消费者正在做一些需要一段时间的事情,那么你实际上并不需要来自并发库的任何花哨的东西。
请注意,顺便说一句,这个例子适用于任何数量的生产者和/或消费者线程。
import java.util.Random;
public class Example {
public static void main(String[] av) {
new Example().go();
}
Object mutex = new Object();
String theString = null;
void go() {
Runnable producer = new Runnable() {
public void run() {
Random rnd = new Random();
try {
for (;;) {
Thread.sleep(rnd.nextInt(10000));
synchronized (mutex) {
theString = "" + System.currentTimeMillis();
System.out.println("Producer: Setting string to " + theString);
mutex.notify();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Runnable consumer = new Runnable() {
public void run() {
try {
String mostRecentValue = null;
Random rnd = new Random();
for (;;) {
synchronized (mutex) {
// we use == because the producer
// creates new string
// instances
if (theString == mostRecentValue) {
System.out.println("Consumer: Waiting for new value");
mutex.wait();
System.out.println("Consumer: Producer woke me up!");
} else {
System.out.println("Consumer: There's a new value waiting for me");
}
mostRecentValue = theString;
}
System.out.println("Consumer: processing " + mostRecentValue);
Thread.sleep(rnd.nextInt(10000));
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
new Thread(producer).start();
new Thread(consumer).start();
}
}
这将是非常低效的。消费者线程在等待工作时不应该阻塞CPU。 – 2009-02-06 16:08:18
实际上,这里的消费者会消耗所有的CPU,因为循环中没有wait()(这可能就是你所说的“block”)。这就是为什么,我认为,OP想要使用现有的JDK类 - 写一个破碎的本地并发对象很容易。 – kdgregory 2009-02-06 16:11:16
这两个提示都是真的,我确定了第一个,谢谢。 – 2009-02-06 16:14:44