1. 程式人生 > >java高階之執行緒池

java高階之執行緒池

1、執行緒併發庫根據案例進行原理分析

場景:多客戶訪問Tomcat的伺服器的原理 ,每一個客戶訪問Tomcat伺服器,Tomcat伺服器都要建立一個執行緒去處理,這就涉及到多執行緒併發的問題。
現實中舉例:比如一個人李三結婚,他有4個朋友分別是F1,F2,F3,F4,那麼針對結婚當天李三要接待所有的客人,李三不可能和每一個客人細細詳談,所以他是這樣做的,他只負責收禮金,然後針對每一個客人建立一個執行緒,然後安排F1,F2,F3,F4去和客人們詳談,如果其中一個詳談結束了,那麼它會檢查還有客戶沒有接待嗎,直到所有的客人都接待完成。

   注意:如果伺服器的客戶訪問很多,那麼伺服器要不斷的建立和銷燬執行緒,這將嚴重影響伺服器的效能。如果來一個客人,李三就要建立一個執行緒即安排一個新的人去接待,那是不可能的。解決辦法是,F1,F2,F3,F4,如果有誰空閒下來了,那麼就由誰去接待。做到執行緒的複用。針對以上的列子Java1.5後提供了執行緒池來解決上述問題。

2、執行緒池的概念

執行緒池,首先建立一些執行緒,他們的集合稱之為執行緒池,當執行緒池接待到一個任務後,會從執行緒池中選擇一個空閒的執行緒去完成該任務,該任務完成後,並不是自動的結束執行緒,而是將執行緒放入到執行緒池中,等待下次執行任務。

3、執行緒池的分類及用法

執行緒池分為四種:                          固定執行緒數量的執行緒池(newFixedThreadPool()),                          自動擴充執行緒數量的執行緒池(newCachedThreadPool()),                          單執行緒池(newSingleThreadExector())、
                         定時器執行緒池(newScheduledThreadPool())。

(1)固定執行緒池:只有固定的數量n個執行緒,建立任務會放在池子裡面,只要n個執行緒中有的空閒的執行緒,就會檢查池子裡有沒有沒有執行的任務,如果有還沒有執行的任務,則會執行,如果沒有任務了,那麼執行緒不會自定死亡,會等待任務的出現。注意,該執行緒池中始終有n個執行緒存在不會死的。

 public class ThreadFixedPoolTest{
  
    public static void main(){
        ExecutorService executorService = Executor.newFixedThreadPool(3);//池子裡始終有3個執行緒,多的任務排隊等
        for(int i=0;i<10;i++){
             final int task = i;
             executorService.execute(new Runnable(){
                  @Override
                   public void run(){
                       for(int j=0; j<10;j++){
                          System.out.println(Thread.currentThread().getName()+ " do loop "+j+" form task " +task);
                       }
                   }
             })
        }

        System.out.println("all 10 task have commit");
    }

}


</pre><span style="font-size:18px">(2)</span><span style="font-size:18px">自動擴充執行緒數量的執行緒池,又叫做快取執行緒池,所謂快取,就是當執行緒池中的執行緒數量不夠完成任務的時候,會自動給再建立執行緒去完成任務這就是自動擴充。</span></div><div><span style="font-size:18px"><span style="font-size:18px"></span></span></div><div><span style="font-size:18px"><span style="font-size:18px"></span></span><div><pre name="code" class="java">public class ThreadFixedPoolTest2{
  
    public static void main(){
        ExecutorService executorService = Executor.newCachedThreadPool();//會自動擴充執行緒池中執行緒數量
        for(int i=0;i<10;i++){
             final int task = i;
             executorService.execute(new Runnable(){
                  @Override
                   public void run(){
                       for(int j=0; j<10;j++){
                          System.out.println(Thread.currentThread().getName()+ " do loop "+j+" form task " +task);
                       }
                   }
             })
        }

        System.out.println("all 10 task have commit");
    }

}


(3)單執行緒池,就是執行緒池中只有單個執行緒,如果執行緒池中該執行緒死了,那麼會自動復活一個執行緒。所以該種執行緒池中始終有且只有一個執行緒。
public class ThreadSinglePoolTest {

public static void main(String[] args) {

//有點類似newFixedThreadPool(1)
ExecutorService executorService=Executors.newSingleThreadExecutor();
for(int i=0;i<5;i++){
final int task=i;
executorService.execute(new Runnable() {
@Override
public void run() {
   for(int j=0;j<10;j++){
      System.out.println(Thread.currentThread().getName()+" do loop "+j+ " form task "+task);
           }
}
});
}

executorService.shutdown();
}
}

(4)定時器執行緒池,
 //10秒之後爆炸
 ScheduledExecutorService executorService=Executors.newScheduledThreadPool(3);
 executorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("bombing");
}
}, 10, TimeUnit.SECONDS);

//10秒之後爆炸,以後每隔2秒爆炸
Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("bombing");
}
}, 10, 2, TimeUnit.SECONDS);


注意:ScheduledExecutorService 的schedule方法,返回的ScheduleFuture物件可以取消任務。其次ScheduledExecutorService 支援間隔重複任務的定時方式,不直接支援絕對時方式,需要轉化為相對時間方式。 (5)shutdown 與 shutdownNow     shutdown呼叫後,不可以再submit新的task,已經submit的將繼續執行。 shutdownNow試圖停止當前正執行的task,並返回尚未執行的task的list