public class LogWriter {
private long count = 0;
private volatile boolean isShutDown;
private final LogThread logThread;
private final BlockingQueue<String> queue;
public LogWriter(PrintWriter writer) {
this.logThread = new LogThread(writer);
this.queue = new LinkedBlockingQueue<>();
}
public void start() {
logThread.start();
}
public void end() {
// 中斷take阻塞
logThread.interrupt();
// 判斷是否停止,和interrupt區別,需要把日誌打印完,在停止線程
isShutDown = true;
}
public void log(String message) {
try {
synchronized (this) {
// 如果停止了,就不能在添加日誌
if (isShutDown) {
throw new IllegalStateException("已關閉");
}
// 記錄日誌數量,在關閉的時候,打印完成
count++;
}
queue.put(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class LogThread extends Thread {
private PrintWriter writer;
public LogThread(PrintWriter writer) {
this.writer = writer;
}
@Override
public void run() {
try {
while (true) {
try {
// 限判斷,在打印,判斷需要加鎖
synchronized (LogWriter.this) {
if (isShutDown && count == 0) {
break;
}
}
writer.println(queue.take());
// 64位機.long-- 操作並非原子,加鎖保證原子性和可見性
synchronized (LogWriter.this) {
count--;
}
} catch (InterruptedException e) {
// 繼續執行
e.printStackTrace();
}
}
} finally {
writer.close();
}
}
}
public static void main(String[] args) {
PrintWriter printWriter = new PrintWriter(System.out, true);
LogWriter logWriter = new LogWriter(printWriter);
logWriter.start();
logWriter.log("test");
logWriter.end();
System.out.println("main end");
}
}