1. 程式人生 > >關閉執行緒的正確姿勢,實現“優雅”的中斷

關閉執行緒的正確姿勢,實現“優雅”的中斷

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();
           }
       }
   }
}