關閉執行緒的正確姿勢,實現“優雅”的中斷
阿新 • • 發佈:2019-01-09
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 LogService(Writer writer) {
this.queue = new LinkedBlockingQueue<String>();
this.loggerThread = new LoggerThread();
this.writer = new PrintWriter(writer);
}
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 */
}
}
} finally {
writer.close();
}
}
}
}
private final BlockingQueue<String> queue;
private final LoggerThread loggerThread;
private final PrintWriter writer;
@GuardedBy("this") private boolean isShutdown;
// 訊號量 用來記錄佇列中訊息的個數
@GuardedBy("this") private int reservations;
public LogService(Writer writer)
this.queue = new LinkedBlockingQueue<String>();
this.loggerThread = new LoggerThread();
this.writer = new PrintWriter(writer);
}
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 */
}
}
} finally {
writer.close();
}
}
}
}