日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
面試突擊:線程池有幾種創(chuàng)建方式?推薦使用哪種?
  • 通過 ThreadPoolExecutor 手動(dòng)創(chuàng)建線程池。
  • 通過 Executors 執(zhí)行器自動(dòng)創(chuàng)建線程池。

而以上兩類創(chuàng)建線程池的方式,又有 7 種具體實(shí)現(xiàn)方法,這 7 種實(shí)現(xiàn)方法分別是:

專注于為中小企業(yè)提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)興平免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了千余家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

  • Executors.newFixedThreadPool:創(chuàng)建一個(gè)固定大小的線程池,可控制并發(fā)的線程數(shù),超出的線程會(huì)在隊(duì)列中等待。
  • Executors.newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池,若線程數(shù)超過處理所需,緩存一段時(shí)間后會(huì)回收,若線程數(shù)不夠,則新建線程。
  • Executors.newSingleThreadExecutor:創(chuàng)建單個(gè)線程數(shù)的線程池,它可以保證先進(jìn)先出的執(zhí)行順序。
  • Executors.newScheduledThreadPool:創(chuàng)建一個(gè)可以執(zhí)行延遲任務(wù)的線程池。
  • Executors.newSingleThreadScheduledExecutor:創(chuàng)建一個(gè)單線程的可以執(zhí)行延遲任務(wù)的線程池。
  • Executors.newWorkStealingPool:創(chuàng)建一個(gè)搶占式執(zhí)行的線程池(任務(wù)執(zhí)行順序不確定)【JDK 1.8 添加】。
  • ThreadPoolExecutor:手動(dòng)創(chuàng)建線程池的方式,它創(chuàng)建時(shí)最多可以設(shè)置 7 個(gè)參數(shù)。

接下來我們分別來看這 7 種線程池的具體使用。

1.FixedThreadPool

創(chuàng)建一個(gè)固定大小的線程池,可控制并發(fā)線程數(shù)。使用 FixedThreadPool 創(chuàng)建 2 個(gè)固定大小的線程池,具體實(shí)現(xiàn)代碼如下:

public static void fixedThreadPool() {
// 創(chuàng)建 2 個(gè)線程的線程池
ExecutorService threadPool = Executors.newFixedThreadPool(2);

// 創(chuàng)建任務(wù)
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("任務(wù)被執(zhí)行,線程:" + Thread.currentThread().getName());
}
};

// 線程池執(zhí)行任務(wù)(一次添加 4 個(gè)任務(wù))
// 執(zhí)行任務(wù)的方法有兩種:submit 和 execute
threadPool.submit(runnable); // 執(zhí)行方式 1:submit
threadPool.execute(runnable); // 執(zhí)行方式 2:execute
threadPool.execute(runnable);
threadPool.execute(runnable);
}

以上程序的執(zhí)行結(jié)果如下圖所示:

如果覺得以上方法比較繁瑣,還用使用以下簡單的方式來實(shí)現(xiàn)線程池的創(chuàng)建和使用:

public static void fixedThreadPool() {
// 創(chuàng)建線程池
ExecutorService threadPool = Executors.newFixedThreadPool(2);
// 執(zhí)行任務(wù)
threadPool.execute(() -> {
System.out.println("任務(wù)被執(zhí)行,線程:" + Thread.currentThread().getName());
});
}

2.CachedThreadPool

創(chuàng)建一個(gè)可緩存的線程池,若線程數(shù)超過任務(wù)所需,那么多余的線程會(huì)被緩存一段時(shí)間后才被回收,若線程數(shù)不夠,則會(huì)新建線程。CachedThreadPool 使用示例如下:

public static void cachedThreadPool() {
// 創(chuàng)建線程池
ExecutorService threadPool = Executors.newCachedThreadPool();
// 執(zhí)行任務(wù)
for (int i = 0; i < 10; i++) {
threadPool.execute(() -> {
System.out.println("任務(wù)被執(zhí)行,線程:" + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
});
}
}

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,線程池創(chuàng)建了 10 個(gè)線程來執(zhí)行相應(yīng)的任務(wù)。

使用場景

CachedThreadPool 是根據(jù)短時(shí)間的任務(wù)量來決定創(chuàng)建的線程數(shù)量的,所以它適合短時(shí)間內(nèi)有突發(fā)大量任務(wù)的處理場景。

3.SingleThreadExecutor

創(chuàng)建單個(gè)線程的線程池,它可以保證先進(jìn)先出的執(zhí)行順序。SingleThreadExecutor 使用示例如下:

public static void singleThreadExecutor() {
// 創(chuàng)建線程池
ExecutorService threadPool = Executors.newSingleThreadExecutor();
// 執(zhí)行任務(wù)
for (int i = 0; i < 10; i++) {
final int index = i;
threadPool.execute(() -> {
System.out.println(index + ":任務(wù)被執(zhí)行");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
});
}
}

以上程序的執(zhí)行結(jié)果如下圖所示:

單個(gè)線程的線程池有什么意義?

單個(gè)線程的線程池相比于線程來說,它的優(yōu)點(diǎn)有以下 2 個(gè):

  • 可以復(fù)用線程:即使是單個(gè)線程池,也可以復(fù)用線程。
  • 提供了任務(wù)管理功能:單個(gè)線程池也擁有任務(wù)隊(duì)列,在任務(wù)隊(duì)列可以存儲(chǔ)多個(gè)任務(wù),這是線程無法實(shí)現(xiàn)的,并且當(dāng)任務(wù)隊(duì)列滿了之后,可以執(zhí)行拒絕策略,這些都是線程不具備的。

4.ScheduledThreadPool

創(chuàng)建一個(gè)可以執(zhí)行延遲任務(wù)的線程池。使用示例如下:

public static void scheduledThreadPool() {
// 創(chuàng)建線程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
// 添加定時(shí)執(zhí)行任務(wù)(1s 后執(zhí)行)
System.out.println("添加任務(wù),時(shí)間:" + new Date());
threadPool.schedule(() -> {
System.out.println("任務(wù)被執(zhí)行,時(shí)間:" + new Date());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
}, 1, TimeUnit.SECONDS);
}

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,任務(wù)在 1 秒之后被執(zhí)行了,實(shí)現(xiàn)了延遲 1s 再執(zhí)行任務(wù)。

5.SingleThreadScheduledExecutor

創(chuàng)建一個(gè)單線程的可以執(zhí)行延遲任務(wù)的線程池,此線程池可以看作是 ScheduledThreadPool 的單線程池版本。它的使用示例如下:

public static void SingleThreadScheduledExecutor() {
// 創(chuàng)建線程池
ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
// 添加定時(shí)執(zhí)行任務(wù)(2s 后執(zhí)行)
System.out.println("添加任務(wù),時(shí)間:" + new Date());
threadPool.schedule(() -> {
System.out.println("任務(wù)被執(zhí)行,時(shí)間:" + new Date());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
}, 2, TimeUnit.SECONDS);
}

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,任務(wù)在 2 秒之后被執(zhí)行了。

6.newWorkStealingPool

創(chuàng)建一個(gè)搶占式執(zhí)行的線程池(任務(wù)執(zhí)行順序不確定),此方法是 JDK 1.8 版本新增的,因此只有在 JDK 1.8 以上的程序中才能使用。newWorkStealingPool 使用示例如下:

public static void workStealingPool() {
// 創(chuàng)建線程池
ExecutorService threadPool = Executors.newWorkStealingPool();
// 執(zhí)行任務(wù)
for (int i = 0; i < 10; i++) {
final int index = i;
threadPool.execute(() -> {
System.out.println(index + " 被執(zhí)行,線程名:" + Thread.currentThread().getName());
});
}
// 確保任務(wù)執(zhí)行完成
while (!threadPool.isTerminated()) {
}
}

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,任務(wù)的執(zhí)行順序是不確定的,因?yàn)樗菗屨际綀?zhí)行的。

7.ThreadPoolExecutor

ThreadPoolExecutor 是最原始、也是最推薦的手動(dòng)創(chuàng)建線程池的方式,它在創(chuàng)建時(shí)最多提供 7 個(gè)參數(shù)可供設(shè)置。ThreadPoolExecutor 使用示例如下:

public static void myThreadPoolExecutor() {
// 創(chuàng)建線程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
// 執(zhí)行任務(wù)
for (int i = 0; i < 10; i++) {
final int index = i;
threadPool.execute(() -> {
System.out.println(index + " 被執(zhí)行,線程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}

以上程序的執(zhí)行結(jié)果如下圖所示:

ThreadPoolExecutor 相比于其他創(chuàng)建線程池的優(yōu)勢(shì)在于,它可以通過參數(shù)來控制最大任務(wù)數(shù)和拒絕策略,讓線程池的執(zhí)行更加透明和可控,所以在阿里巴巴《Java開發(fā)手冊(cè)》是這樣規(guī)定的:

【強(qiáng)制要求】線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。

說明:Executors 返回的線程池對(duì)象的弊端如下:

1) FixedThreadPool 和 SingleThreadPool:允許的請(qǐng)求隊(duì)列長度為 Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致 OOM。

2)CachedThreadPool:允許的創(chuàng)建線程數(shù)量為 Integer.MAX_VALUE,可能會(huì)創(chuàng)建大量的線程,從而導(dǎo)致 OOM。

總結(jié)

線程池的創(chuàng)建方式總共有以下 7 種:

  • Executors.newFixedThreadPool:創(chuàng)建一個(gè)固定大小的線程池,可控制并發(fā)的線程數(shù),超出的線程會(huì)在隊(duì)列中等待。
  • Executors.newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池,若線程數(shù)超過處理所需,緩存一段時(shí)間后會(huì)回收,若線程數(shù)不夠,則新建線程。
  • Executors.newSingleThreadExecutor:創(chuàng)建單個(gè)線程數(shù)的線程池,它可以保證先進(jìn)先出的執(zhí)行順序。
  • Executors.newScheduledThreadPool:創(chuàng)建一個(gè)可以執(zhí)行延遲任務(wù)的線程池。
  • Executors.newSingleThreadScheduledExecutor:創(chuàng)建一個(gè)單線程的可以執(zhí)行延遲任務(wù)的線程池。
  • Executors.newWorkStealingPool:創(chuàng)建一個(gè)搶占式執(zhí)行的線程池(任務(wù)執(zhí)行順序不確定)【JDK 1.8 添加】。
  • ThreadPoolExecutor:手動(dòng)創(chuàng)建線程池的方式,它創(chuàng)建時(shí)最多可以設(shè)置 7 個(gè)參數(shù)。

而線程池的創(chuàng)建推薦使用最后一種 ThreadPoolExecutor 的方式來創(chuàng)建,因?yàn)槭褂盟梢悦鞔_線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。


分享題目:面試突擊:線程池有幾種創(chuàng)建方式?推薦使用哪種?
新聞來源:http://m.5511xx.com/article/coocsij.html