溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java如何判斷線程池線程是否執行完畢

發布時間:2020-07-22 11:29:56 來源:億速云 閱讀:1077 作者:小豬 欄目:編程語言

這篇文章主要為大家展示了Java如何判斷線程池線程是否執行完畢,內容簡而易懂,希望大家可以學習一下,學習完之后肯定會有收獲的,下面讓小編帶大家一起來看看吧。

在使用多線程的時候有時候我們會使用 java.util.concurrent.Executors的線程池,當多個線程異步執行的時候,我們往往不好判斷是否線程池中所有的子線程都已經執行完畢,但有時候這種判斷卻很有用,例如我有個方法的功能是往一個文件異步地寫入內容,我需要在所有的子線程寫入完畢后在文件末尾寫“---END---”及關閉文件流等,這個時候我就需要某個標志位可以告訴我是否線程池中所有的子線程都已經執行完畢,我使用這種方式來判斷。

public class MySemaphore {

  public static void main(String[] args) throws IOException, InterruptedException {
    final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
    final OutputStream os = new FileOutputStream(stream);
    final OutputStreamWriter writer = new OutputStreamWriter(os);
    final Semaphore semaphore = new Semaphore(10);
    ExecutorService exec = Executors.newCachedThreadPool();

    final long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
      final int num = i;
      Runnable task = new Runnable() {
        @Override
        public void run() {
          try {
            semaphore.acquire();
            writer.write(String.valueOf(num)+"\n");
            semaphore.release();
          } catch (IOException e) {
            e.printStackTrace();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      };
      exec.submit(task);
    }
    exec.shutdown();
    while(true){
      if(exec.isTerminated()){
        writer.write("---END---\n");
        writer.close();
        System.out.println("所有的子線程都結束了!");
        break;
      }
      Thread.sleep(1000);
    }
    final long end = System.currentTimeMillis();
    System.out.println((end-start)/1000);
  }
}

當調用ExecutorService.shutdown方法的時候,線程池不再接收任何新任務,但此時線程池并不會立刻退出,直到添加到線程池中的任務都已經處理完成,才會退出。在調用shutdown方法后我們可以在一個死循環里面用isTerminated方法判斷是否線程池中的所有線程已經執行完畢,如果子線程都結束了,我們就可以做關閉流等后續操作了。

判斷線程池中的線程是否全部執行完畢的另外一種解決方案則是使用閉鎖(CountDownLatch)來實現,CountDownLatch是一種靈活的閉鎖實現,它可以使一個或多個線程等待一組事件發生。閉鎖狀態包括一個計數器,該計數器被初始化為一個正數,表示需要等待的事件數量。countDown方法遞減計數器,表示有一個事件已經發生了,而await方法等待計數器達到零,即表示需要等待的事情都已經發生??梢允褂瞄]鎖來這樣設計程序達到目的:

public class CountDownLatchApproach {
  public static void main(String[] args) throws IOException, InterruptedException {
    final int nThreads = 10;
    final CountDownLatch endGate = new CountDownLatch(nThreads);
    final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
    final OutputStream os = new FileOutputStream(stream);
    final OutputStreamWriter writer = new OutputStreamWriter(os);
    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < nThreads; i++) {
      final int num = i;
      Runnable task = new Runnable() {
        @Override
        public void run() {
          try {
            writer.write(String.valueOf(num)+"\n");
          } catch (IOException e) {
            e.printStackTrace();
          } finally {
            endGate.countDown();
          }
        }
      };
      exec.submit(task);
    }
    endGate.await();
    writer.write("---END---\n");
    writer.close();
  }
}

這種解決方案雖然可以達到目的但是性能差到沒朋友,我更傾向于使用第一種方案。

現在我們有了更優雅的第三種方案,它的執行性能也不錯。

public class MySemaphore {

  public static void main(String[] args) throws IOException, InterruptedException {
    final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
    final OutputStream os = new FileOutputStream(stream);
    final OutputStreamWriter writer = new OutputStreamWriter(os);
    final Semaphore semaphore = new Semaphore(10);
    ExecutorService exec = Executors.newCachedThreadPool();

    final long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
      final int num = i;
      Runnable task = new Runnable() {
        @Override
        public void run() {
          try {
            semaphore.acquire();
            writer.write(String.valueOf(num)+"\n");
            semaphore.release();
          } catch (IOException e) {
            e.printStackTrace();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      };
      exec.submit(task);
    }
    exec.shutdown();
    exec.awaitTermination(1, TimeUnit.HOURS);
    writer.write("---END---\n");
    writer.close();
    System.out.println("&Euml;ù&Oacute;&ETH;&micro;&Auml;×&Oacute;&Iuml;&szlig;&sup3;&Igrave;&para;&frac14;&frac12;á&Ecirc;&oslash;&Aacute;&Euml;&pound;&iexcl;");
    final long end = System.currentTimeMillis();
    System.out.println((end-start)/1000);
  }
}

以上就是關于Java如何判斷線程池線程是否執行完畢的內容,如果你們有學習到知識或者技能,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女