1. 程式人生 > >通過Executor來啟動線程比用Thread的start()更好

通過Executor來啟動線程比用Thread的start()更好

對象創建 code splay 大小 延時 ren mar 數量 nds

java5為什麽引入Executor線程池框架

1.new Thread()的缺點

(1) 每次new Thread()耗費性能
(2) 調用new Thread()創建的線程缺乏管理,被稱為野線程,而且可以無限制創建,之間相互競爭,會導致過多占用系統資源,使系統癱瘓
(3) 不利於擴展,比如如定時執行、定期執行

2.采用線程池的優點

(1) 重用存在的線程,減少對象創建、銷毀的開銷,性能佳
(2) 可有效控制最大並發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞
(3) 提供定時執行、定期執行、單線程、並發數控制等功能

java通過Executor提供4種線程池

1.newCachedThreadPool 創建一個可緩存的線程池,調用execute將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線 程並添加到池中。終止並從緩存中移除那些已有 60 秒鐘未被使用的線程

示例:

ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
     Runnable task = new Runnable() {
         @Override
         public void run() {
             System.out.println(Thread.currentThread().getName());
         }
     };
     executor.execute(task);
}

運行結果:可以看出緩存線程池大小是不定值,可以需要創建不同數量的線程,在使用緩存型池時,先查看池中有沒有以前創建的線程,如果有,就復用.如果沒有,就新建新的線程加入池中,緩存型池子通常用於執行一些生存期很短的異步型任務。

2.newFixedThreadPool 創建固定數目線程的線程池,可控制線程最大並發數,超出的線程會在隊列中等待

示例:

ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; i++) {
     Runnable task = new Runnable() {
         @Override
         public void run() {
             System.out.println(Thread.currentThread().getName());
         }
     };
     executor.execute(task);
}

運行結果:總共只會創建2個線程, 開始執行2個線程,當2個線程都處於活動狀態,再次提交的任務都會加入隊列等到其他線程運行結束,當線程處於空閑狀態時會被下一個任務復用。

3.newScheduledThreadPool 創建一個支持定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類

示例:

ExecutorService executor = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 10; i++) {
     Runnable task = new Runnable() {
         @Override
         public void run() {
             System.out.println(Thread.currentThread().getName());
         }
     };
     executor.schedule(task, 3, TimeUnit.SECONDS);
}

運行結果:和newFixedThreadPool類似,不同的是newScheduledThreadPool是延時指定時間之後才執行。

4.newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行

示例:

ExecutorService executor = Executors.newScheduledThreadPool();
for (int i = 0; i < 10; i++) {
     Runnable task = new Runnable() {
         @Override
         public void run() {
             System.out.println(Thread.currentThread().getName());
         }
     };
     executor.execute(task);
}

運行結果:只會創建一個線程,當上一個執行完之後才會執行第二個。

ExecutorService中submit和execute的區別:

相同點:submit和execute都是 ExecutorService 的方法,都是添加線程到線程池中

不同點:submit 有返回值 返回Future , execute沒有,Future可以執行cancle方法(取消執行 ),可以通過get()方法,判斷是否執行成功(null表示執行成功)

通過Executor來啟動線程比用Thread的start()更好