java高階之執行緒池
阿新 • • 發佈:2019-02-19
1、執行緒併發庫根據案例進行原理分析
場景:多客戶訪問Tomcat的伺服器的原理 ,每一個客戶訪問Tomcat伺服器,Tomcat伺服器都要建立一個執行緒去處理,這就涉及到多執行緒併發的問題。現實中舉例:比如一個人李三結婚,他有4個朋友分別是F1,F2,F3,F4,那麼針對結婚當天李三要接待所有的客人,李三不可能和每一個客人細細詳談,所以他是這樣做的,他只負責收禮金,然後針對每一個客人建立一個執行緒,然後安排F1,F2,F3,F4去和客人們詳談,如果其中一個詳談結束了,那麼它會檢查還有客戶沒有接待嗎,直到所有的客人都接待完成。
注意:如果伺服器的客戶訪問很多,那麼伺服器要不斷的建立和銷燬執行緒,這將嚴重影響伺服器的效能。如果來一個客人,李三就要建立一個執行緒即安排一個新的人去接待,那是不可能的。解決辦法是,F1,F2,F3,F4,如果有誰空閒下來了,那麼就由誰去接待。做到執行緒的複用。針對以上的列子Java1.5後提供了執行緒池來解決上述問題。
2、執行緒池的概念
執行緒池,首先建立一些執行緒,他們的集合稱之為執行緒池,當執行緒池接待到一個任務後,會從執行緒池中選擇一個空閒的執行緒去完成該任務,該任務完成後,並不是自動的結束執行緒,而是將執行緒放入到執行緒池中,等待下次執行任務。3、執行緒池的分類及用法
執行緒池分為四種: 固定執行緒數量的執行緒池(newFixedThreadPool()), 自動擴充執行緒數量的執行緒池(newCachedThreadPool()), 單執行緒池(newSingleThreadExector())、(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