3 回答
TA贡献1951条经验 获得超3个赞
而不是让 Consumerextend Runnable你可以改变你的代码来合并一个ScheduledExecutorService每半秒运行一次队列轮询而不是让线程休眠的代码。这方面的一个例子是
public void schedule() {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(() -> {
String str;
try {
while ((str = queue.poll()) != null) {
call(str); // do further processing
}
} catch (IOException e) {
ferpt.felog("svr class", "consumer", "consumer thread", e.getClass().getName() + ": " + e.getMessage());
}
}, 0, 500, TimeUnit.MILLISECONDS);
}
TA贡献1816条经验 获得超6个赞
解决您的问题的正确方法是使用阻塞队列。它为您提供了几个优势:
不浪费cpu忙等待
容量有限 - 假设你有一个快速的生产者,但一个缓慢的消费者 -> 如果队列的大小不受限制,那么你的应用程序很容易达到 OutOfMemory 条件
这是一个小演示,您可以使用它:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProdConsTest {
public static void main(String[] args) throws InterruptedException {
final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
final Runnable producer = () -> {
for (int i = 0; i < 1000; i++) {
try {
System.out.println("Producing: " + i);
queue.put(i);
//Adjust production speed by modifying the sleep time
Thread.sleep(100);
} catch (InterruptedException e) {
//someone signaled us to terminate
break;
}
}
};
final Runnable consumer = () -> {
while (true) {
final Integer integer;
try {
//Uncomment to simulate slow consumer:
//Thread.sleep(1000);
integer = queue.take();
} catch (InterruptedException e) {
//someone signaled us to terminate
break;
}
System.out.println("Consumed: " + integer);
}
};
final Thread consumerThread = new Thread(consumer);
consumerThread.start();
final Thread producerThread = new Thread(producer);
producerThread.start();
producerThread.join();
consumerThread.interrupt();
consumerThread.join();
}
}
现在取消注释sleep()消费者并观察应用程序发生了什么。如果您正在使用基于计时器的解决方案,例如建议的解决方案,ScheduledExecutorService或者您正忙于等待,那么使用快速生产者,队列将无法控制地增长并最终导致您的应用程序崩溃
TA贡献1772条经验 获得超5个赞
当有新消息时,让消费者wait()在一个对象上都可以访问,并让生产者在这个对象上监听。notify()然后,消费者应该删除所有消息,而不仅仅是示例中的单个消息。
添加回答
举报
