gpt4 book ai didi

Java 并发实践 “Listing 7.15. Adding reliable cancellation to LogWriter.”。 loggerThread.interrupt() 有什么意义?

转载 作者:行者123 更新时间:2023-12-01 05:00:56 25 4
gpt4 key购买 nike

我正在阅读 Java Concurrency in Practice 并遇到以下代码片段( list 7.15。向 LogWriter 添加可靠的取消。)。

public class LogService {
private final BlockingQueue<String> queue;
private final LoggerThread loggerThread;
private final PrintWriter writer;
@GuardedBy("this") private boolean isShutdown;
@GuardedBy("this") private int reservations;
public void start() { loggerThread.start(); }
public void stop() {
synchronized (this) { isShutdown = true; }
loggerThread.interrupt();
}
public void log(String msg) throws InterruptedException {
synchronized (this) {
if (isShutdown)
throw new IllegalStateException(...);
++reservations;
}
queue.put(msg);
}
private class LoggerThread extends Thread {
public void run() {
try {
while (true) {
try {
synchronized (LogService.this) {
if (isShutdown && reservations == 0)
break;
}
String msg = queue.take();
synchronized (LogService.this) {
--reservations;
}
writer.println(msg);
} catch (InterruptedException e) { /* retry */ } // interruption policy
}
} finally {
writer.close();
}
}
}
}

LogService用于实现“多日志生产者,单日志消费者”(多线程可以执行log(String msg)任务为了将日志放入queue,一个loggerThread可以消费queue中的日志。

但是 LoggerThread 定义了自己的中断策略,即在 catch block 中“什么都不做”。那么,调用 loggerThread.interrupt(); 有什么意义?

最佳答案

如果我们看一下循环:

while (true) {
try {
synchronized (LogService.this) {
if (isShutdown && reservations == 0)
break;
}
String msg = queue.take();
synchronized (LogService.this) {
--reservations;
}
writer.println(msg);
} catch (InterruptedException e) { /* retry */ } // interruption policy
}

我们看到它有以下行为:

  • 线程阻塞在 queue.take() 中,等待传入的消息。
  • 只要 LogService 没有关闭或仍有消息要记录,它就会循环。
  • 关闭后,如果队列中仍有消息,它们将在循环终止前被记录下来。
  • 如果线程在 LogService 未关闭的情况下以某种方式被中断,则线程继续运行,就好像什么都没有改变一样。这可以防止错误中断中断服务。

catch block 中无事可做,因为跳出循环的代码在循环的其他地方处理。如果你愿意,你可以:

catch (InterruptedException ex) {
synchronized (LogService.this) {
if (isShutdown && reservations == 0) break;
}
}

但那将是无缘无故的重复、冗余代码。我们也不希望在 catch block 中出现无条件的 break,因为我们希望循环直到所有消息都被记录,即使在关闭之后也是如此;同样,您可以将该逻辑放在 catch block 中,但是当循环的其余部分已经完成完全相同的事情时,为什么还要这样做。

并且我们需要调用 loggerThread.interrupt(),因为线程可能在 queue.take() 调用中被阻塞。中断唤醒线程,允许它检查循环中断条件。如果没有中断,线程可能会保持阻塞状态并且永不死亡。

关于Java 并发实践 “Listing 7.15. Adding reliable cancellation to LogWriter.”。 loggerThread.interrupt() 有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59572083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com