介紹new Thread的弊端及Java四種執行緒池的使用
1,執行緒池的作用
執行緒池作用就是限制系統中執行執行緒的數量。
根據系統的環境情況,可以自動或手動設定執行緒數量,達到執行的最佳效果。
少了浪費了系統資源,多了造成系統擁擠效率不高。
用執行緒池控制執行緒數量,其他執行緒排 隊等候。
一個任務執行完畢,再從佇列的中取最前面的任務開始執行。
若佇列中沒有等待程式,執行緒池的這一資源處於等待。
當一個新任務需要執行時,如果執行緒池 中有等待的工作執行緒,就可以開始執行了;否則進入等待佇列。
2,為什麼要用執行緒池?
1.減少了建立和銷燬執行緒的次數,每個工作執行緒都可以被重複利用,可執行多個任務。
2.可以根據系統的承受能力,調整執行緒池中工作線執行緒的數目,防止因為消耗過多的記憶體,而把伺服器累趴下(每個執行緒需要大約1MB記憶體,執行緒開的越多,消耗的記憶體也就越大,最後當機)。
Java裡面執行緒池的頂級介面是Executor
,但是嚴格意義上講Executor
並不是一個執行緒池,而只是一個執行執行緒的工具。真正的執行緒池介面是ExecutorService
。
3,比較重要的幾個類
類 | 描述 |
---|---|
ExecutorService | 真正的執行緒池介面。 |
ScheduledExecutorService | 能和Timer/TimerTask類似,解決那些需要任務重複執行的問題。 |
ThreadPoolExecutor | ExecutorService的預設實現。 |
ScheduledThreadPoolExecutor | 繼承ThreadPoolExecutor的ScheduledExecutorService介面實現,週期性任務排程的類實現。 |
4,new Thread的弊端
public class TestNewThread {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("start");
}
}).start();
}
}
複製程式碼
執行一個非同步任務你還只是如下new Thread嗎?
那你就out太多了,new Thread的弊端如下:
1.每次new Thread新建物件效能差。
2.執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致當機或oom。
3.缺乏更多功能,如定時執行、定期執行、執行緒中斷。
相比new Thread,Java提供的四種執行緒池的好處在於:
1.重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
2.可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
3.提供定時執行、定期執行、單執行緒、併發數控制等功能。
四種執行緒池
Java通過Executors提供四種執行緒池,分別為:
1,newCachedThreadPoo
建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
2,newFixedThreadPool
建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
3,newScheduledThreadPool
建立一個定長執行緒池,支援定時及週期性任務執行。
4,newSingleThreadExecutor
建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
示例
1,newCachedThreadPool
建立一個可快取的執行緒池。如果執行緒池的大小超過了處理任務所需要的執行緒, 那麼就會回收部分空閒(60秒不執行任務)的執行緒,當任務數增加時,此執行緒池又可以智慧的新增新執行緒來處理任務。此執行緒池不會對執行緒池大小做限制,執行緒池大小完全依賴於作業系統(或者說JVM)能夠建立的最大執行緒大小。
package io.ymq.thread.demo1;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 描述: 建立一個可快取的執行緒池。如果執行緒池的大小超過了處理任務所需要的執行緒,那麼就會回收部分空閒(60秒不執行任務)的執行緒,當任務數增加時,此執行緒池又可以智慧的新增新執行緒來處理任務。
* 此執行緒池不會對執行緒池大小做限制,執行緒池大小完全依賴於作業系統(或者說JVM)能夠建立的最大執行緒大小。
*
* @author yanpenglei
* @create 2017-10-12 11:13
**/
public class TestNewCachedThreadPool {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("執行:" + index + ",執行緒名稱:" + threadName);
}
});
}
}
}
複製程式碼
響應:
執行:1,執行緒名稱:pool-1-thread-1
執行:2,執行緒名稱:pool-1-thread-1
執行:3,執行緒名稱:pool-1-thread-1
執行:4,執行緒名稱:pool-1-thread-1
執行:5,執行緒名稱:pool-1-thread-1
執行:6,執行緒名稱:pool-1-thread-1
執行:7,執行緒名稱:pool-1-thread-1
執行:8,執行緒名稱:pool-1-thread-1
執行:9,執行緒名稱:pool-1-thread-1
執行:10,執行緒名稱:pool-1-thread-1
複製程式碼
2,newFixedThreadPool
描述:建立固定大小的執行緒池。每次提交一個任務就建立一個執行緒,直到執行緒達到執行緒池的最大大小。
執行緒池的大小一旦達到最大值就會保持不變,如果某個執行緒因為執行異常而結束,那麼執行緒池會補充一個新執行緒。
package io.ymq.thread.demo2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 描述:建立固定大小的執行緒池。每次提交一個任務就建立一個執行緒,直到執行緒達到執行緒池的最大大小。
* 執行緒池的大小一旦達到最大值就會保持不變,如果某個執行緒因為執行異常而結束,那麼執行緒池會補充一個新執行緒。
*
* @author yanpenglei
* @create 2017-10-12 11:30
**/
public class TestNewFixedThreadPool {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
String threadName = Thread.currentThread().getName();
System.out.println("執行:" + index + ",執行緒名稱:" + threadName);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
複製程式碼
因為執行緒池大小為3,每個任務輸出index後sleep 2秒,所以每兩秒列印3個數字,和執行緒名稱。
響應:
執行:2,執行緒名稱:pool-1-thread-2
執行:3,執行緒名稱:pool-1-thread-3
執行:1,執行緒名稱:pool-1-thread-1
執行:4,執行緒名稱:pool-1-thread-1
執行:6,執行緒名稱:pool-1-thread-2
執行:5,執行緒名稱:pool-1-thread-3
執行:7,執行緒名稱:pool-1-thread-1
執行:9,執行緒名稱:pool-1-thread-3
執行:8,執行緒名稱:pool-1-thread-2
執行:10,執行緒名稱:pool-1-thread-1
複製程式碼
3,newScheduledThreadPool
建立一個定長執行緒池,支援定時及週期性任務執行。延遲執行
package io.ymq.thread.demo3;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 描述:建立一個定長執行緒池,支援定時及週期性任務執行。延遲執行
*
* @author yanpenglei
* @create 2017-10-12 11:53
**/
public class TestNewScheduledThreadPool {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("表示延遲3秒執行。");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("表示延遲1秒後每3秒執行一次。");
}
}, 1, 3, TimeUnit.SECONDS);
}
}
複製程式碼
表示延遲1秒後每3秒執行一次。
表示延遲3秒執行。
表示延遲1秒後每3秒執行一次。
表示延遲1秒後每3秒執行一次。
表示延遲1秒後每3秒執行一次。
表示延遲1秒後每3秒執行一次。
複製程式碼
4,newSingleThreadExecutor
建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
package io.ymq.thread.demo4;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 描述:建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
*
* @author yanpenglei
* @create 2017-10-12 12:05
**/
public class TestNewSingleThreadExecutor {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 1; i <= 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
String threadName = Thread.currentThread().getName();
System.out.println("執行:" + index + ",執行緒名稱:" + threadName);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
複製程式碼
結果依次輸出,相當於順序執行各個任務。
響應:
執行:1,執行緒名稱:pool-1-thread-1
執行:2,執行緒名稱:pool-1-thread-1
執行:3,執行緒名稱:pool-1-thread-1
執行:4,執行緒名稱:pool-1-thread-1
執行:5,執行緒名稱:pool-1-thread-1
執行:6,執行緒名稱:pool-1-thread-1
執行:7,執行緒名稱:pool-1-thread-1
執行:8,執行緒名稱:pool-1-thread-1
執行:9,執行緒名稱:pool-1-thread-1
執行:10,執行緒名稱:pool-1-thread-1
複製程式碼
Contact
- 作者:鵬磊
- 出處:www.ymq.io
- Email:admin@souyunku.com
- 版權歸作者所有,轉載請註明出處
- Wechat:關注公眾號,搜雲庫,專注於開發技術的研究與知識分享