1.線程池的概念與Executors類的應用
應用需求:如果訪問服務器的客戶端很多,那麼服務器要不斷的創建和銷燬線程,這將嚴重的影響服務器的性能
解決方法:首先創建一些線程,它們的集合稱爲線程池,當服務器接受到一個客戶請求後,就從線程池中取出一個空閒的線程爲之服務,服務完後不關閉該線程,而是將線程還回到線程池中。
創建固定大小的線程池;
創建緩存線程池;
創建單一線程池(可以實現線程死掉後重新啓動,即如果線程死掉,會自動重現創建一個替補線程來接替運行任務);
注意:在線程池的編程模式下,任務是提交給整個線程池的,而不是直接交給某個線程;線程池在拿到任務後,它就在內部找有無空閒的線程,再把任務交給某個空閒的線程,這就是封裝。記住,任務是提交給整個線程池的,一個線程同時只能執行一個任務,但可同時向一個線程池提交多個任務。
2.關閉線程池
shutdown與shutdownNow的比較:
shutdown: 啓動一次順序關閉,執行以前提交的任務,但不接受新任務。
shutdownNow: 試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,並返回等待執行的任務列表。
3.用線程池啓動定時器
ScheduledExecutorService newScheduledThreadPool(int corePoolSize):
創建一個線程池,它可安排在給定延遲後運行命令或者定期地執行。
演示代碼如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class ThreadPool {
public static void main(String[] args){
threadPoolTest();
//scheduledThreadPoolTest();
}
private static void threadPoolTest() {
//1.創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程
//ExecutorService threadPool=Executors.newFixedThreadPool(3);
//2.創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們
//ExecutorService threadPool=Executors.newCachedThreadPool();
//3.創建一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程
ExecutorService threadPool=Executors.newSingleThreadExecutor();
for(int i=1;i<=10;i++){
final int taskNum=i;
threadPool.execute(new Runnable(){//十個任務,但始終只有三個線程
public void run(){
System.out.println(Thread.currentThread().getName()+" is running ..... for task "+taskNum);
}
});
}
//沒有新的任務到來,線程就會等待,線程不死,程序就不會結束,除非顯示shutdown
threadPool.shutdown();
// 試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,即立即關閉
//threadPool.shutdownNow();
}
private static void scheduledThreadPoolTest() {
Runnable r=new Runnable(){
@Override
public void run() {
System.out.println("bombing......");
}
};
//10秒後執行
//ScheduledFuture<?> sf=Executors.newScheduledThreadPool(3).schedule(r, 10, TimeUnit.SECONDS);
//4秒後開始執行,每2秒執行一次
Executors.newScheduledThreadPool(3).scheduleAtFixedRate(r, 4, 2, TimeUnit.SECONDS);
}
}