程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 簡略引見Java編程中的線程池

簡略引見Java編程中的線程池

編輯:關於JAVA

簡略引見Java編程中的線程池。本站提示廣大學習愛好者:(簡略引見Java編程中的線程池)文章只能為提供參考,不一定能成為您想要的結果。以下是簡略引見Java編程中的線程池正文


從 Java 5 開端,Java 供給了本身的線程池。線程池就是一個線程的容器,每次只履行額外數目的線程。 java.util.concurrent.ThreadPoolExecutor 就是如許的線程池。它很靈巧,但應用起來也比擬龐雜,本文就對其做一個引見。

起首是結構函數。以最簡略的結構函數為例:

public ThreadPoolExecutor( 
      int corePoolSize, 
      int maximumPoolSize, 
      long keepAliveTime, 
      TimeUnit unit, 
      BlockingQueue<Runnable> workQueue) 

看起來挺龐雜的。這裡引見一下。
corePoolSize 指的是保存的線程池年夜小。
maximumPoolSize 指的是線程池的最年夜年夜小。
keepAliveTime 指的是余暇線程停止的超不時間。
unit 是一個列舉,表現 keepAliveTime 的單元。
workQueue 表現寄存義務的隊列。
我們可以從線程池的任務進程中懂得這些參數的意義。線程池的任務進程以下:

1、線程池剛創立時,外面沒有一個線程。義務隊列是作為參數傳出去的。不外,就算隊列外面有義務,線程池也不會立時履行它們。
 
2、當挪用 execute() 辦法添加一個義務時,線程池會做以下斷定:
    a. 假如正在運轉的線程數目小於 corePoolSize,那末立時創立線程運轉這個義務;
    b. 假如正在運轉的線程數目年夜於或等於 corePoolSize,那末將這個義務放入隊列。
    c. 假如這時候候隊列滿了,並且正在運轉的線程數目小於 maximumPoolSize,那末照樣要創立線程運轉這個義務;
    d. 假如隊列滿了,並且正在運轉的線程數目年夜於或等於 maximumPoolSize,那末線程池會拋出異常,告知挪用者“我不克不及再接收義務了”。
 
3、當一個線程完成義務時,它會從隊列中取下一個義務來履行。
 
4、當一個線程無事可做,跨越必定的時光(keepAliveTime)時,線程池會斷定,假如以後運轉的線程數年夜於 corePoolSize,那末這個線程就被停失落。所以線程池的一切義務完成後,它終究會壓縮到 corePoolSize 的年夜小。
 
如許的進程解釋,其實不是先參加義務就必定會先履行。假定隊列年夜小為 10,corePoolSize 為 3,maximumPoolSize 為 6,那末當參加 20 個義務時,履行的次序就是如許的:起首履行義務 1、2、3,然前任務 4~13 被放入隊列。這時候候隊列滿了,義務 14、15、16 會被立時履行,而義務 17~20 則會拋出異常。終究次序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。上面是一個線程池應用的例子:

public static void main(String[] args) { 
  BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); 
  ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.DAYS, queue); 
  
  for (int i = 0; i < 20; i++) { 
    executor.execute(new Runnable() { 
  
      public void run() { 
        try { 
          Thread.sleep(1000); 
        } catch (InterruptedException e) { 
          e.printStackTrace(); 
        } 
        System.out.println(String.format("thread %d finished", this.hashCode())); 
      } 
    }); 
  } 
  executor.shutdown(); 
} 

對這個例子的解釋以下:
 
1、BlockingQueue 只是一個接口,經常使用的完成類有 LinkedBlockingQueue 和 ArrayBlockingQueue。用 LinkedBlockingQueue 的利益在於沒有年夜小限制。如許的話,由於隊列不會滿,所以 execute() 不會拋出異常,而線程池中運轉的線程數也永久不會跨越 corePoolSize 個,keepAliveTime 參數也就沒成心義了。
 
2、shutdown() 辦法不會壅塞。挪用 shutdown() 辦法以後,主線程就立時停止了,而線程池會持續運轉直到一切義務履行完才會停滯。假如不挪用 shutdown() 辦法,那末線程池會一向堅持下去,以便隨時添加新的義務。
 
到這裡關於這個線程池還只是引見了一小部門。ThreadPoolExecutor 具有很強的可擴大性,不外擴大它的條件是要熟習它的任務方法。前面的文章將會引見若何擴大 ThreadPoolExecutor 類。

ava.util.concurrent.ThreadPoolExecutor 類供給了豐碩的可擴大性。你可以經由過程創立它的子類來自界說它的行動。例如,我願望當每一個義務停止以後打印一條新聞,但我又沒法修正義務對象,那末我可以如許寫:

ThreadPoolExecutor executor = new ThreadPoolExecutor(size, maxSize, 1, TimeUnit.DAYS, queue) {
  @Override
  protected void afterExecute(Runnable r, Throwable t) {
    System.out.println("Task finished.");
  }
};


除 afterExecute 辦法以外,ThreadPoolExecutor 類還有 beforeExecute() 和 terminated() 辦法可以重寫,分離是在義務履行之前和全部線程池停滯以後履行。


除可以添加義務履行前後的舉措以外, ThreadPoolExecutor 還許可你自界說當添加義務掉敗後的履行戰略。你可以挪用線程池的 setRejectedExecutionHandler() 辦法,用自界說的 RejectedExecutionHandler 對象調換現有的戰略。 ThreadPoolExecutor 供給 4 個現有的戰略,分離是:
ThreadPoolExecutor.AbortPolicy:表現謝絕義務並拋出異常
ThreadPoolExecutor.DiscardPolicy:表現謝絕義務但不做任何舉措
ThreadPoolExecutor.CallerRunsPolicy:表現謝絕義務,並在挪用者的線程中直接履行該義務
ThreadPoolExecutor.DiscardOldestPolicy:表現先拋棄義務隊列中的第一個義務,然後把這個義務加進隊列。
這裡是一個例子:
ThreadPoolExecutor executor = new ThreadPoolExecutor(size, maxSize, 1, TimeUnit.DAYS, queue);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

除此以外,你也能夠經由過程完成 RejectedExecutionHandler 接口來編寫本身的戰略。上面是一個例子:

ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue,
    new RejectedExecutionHandler() {
      public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println(String.format("Task %d rejected.", r.hashCode()));
      }
    }
);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved