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()
然后,消費者應該刪除所有消息,而不僅僅是示例中的單個消息。
添加回答
舉報