線程池主要參數(shù)有哪些

這篇文章主要介紹“線程池主要參數(shù)有哪些”,在日常操作中,相信很多人在線程池主要參數(shù)有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”線程池主要參數(shù)有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

創(chuàng)新互聯(lián)公司服務項目包括宿遷網(wǎng)站建設、宿遷網(wǎng)站制作、宿遷網(wǎng)頁制作以及宿遷網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,宿遷網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到宿遷省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

(一)什么是線程池

線程(thread)是操作系統(tǒng)能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位,我們的程序最終都是由線程進行運作。在Java中,創(chuàng)建和銷毀線程的動作是很消耗資源的,因此就出現(xiàn)了所謂“池化資源”技術。

線程池是池化資源技術的一個應用,所謂線程池,顧名思義就是預先按某個規(guī)定創(chuàng)建若干個可執(zhí)行線程放入一個容器中(線程池),需要使用的時候從線程池中去取,用完之后不銷毀而是放回去,從而減少了線程創(chuàng)建和銷毀的次數(shù),達到節(jié)約資源的目的。

(二)為什么要使用線程池

2.1 降低資源消耗

前面已經(jīng)講到線程池的出現(xiàn)減少了線程創(chuàng)建和銷毀的次數(shù),每個線程都可以被重復利用,可執(zhí)行多個任務。

2.2 提高系統(tǒng)的響應速度

每當有任務到來時,直接復用線程池中的線程,而不需要等待新線程的創(chuàng)建,這個動作可以帶來響應速度的提升

2.3 防止過多的線程搞壞系統(tǒng)

可以根據(jù)系統(tǒng)的承受能力,調整線程池中的工作線程的數(shù)量,防止因為線程過多服務器變慢或死機。java一個線程默認占用空間為1M,可以想象一旦手動創(chuàng)建線程過多極有可能導致內存溢出。

(三)線程池主要參數(shù)

我們可以用Executors類來創(chuàng)建一些常用的線程池,但是像阿里是禁止直接通過Executors類直接創(chuàng)建線程池的,具體的原因稍后再談。

在了解Executors類所提供的幾個線程池前,我們首先來了解一下 ThreadPoolExecutor的主要參數(shù),ThreadPoolExecutor是創(chuàng)建線程池的類,我們選取參數(shù)最多的構造方法來看一下:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
名稱類型含義
corePoolSizeint核心線程池的大小
maximumPoolSizeint最大線程池大小
keepAliveTimelong線程最大空閑時間
unitTimeUnit時間單位
workQueueBlockingQueue<Runnable>線程等待隊列
threadFactoryThreadFactory線程創(chuàng)建工程
handlerRejectedExecutionHandler拒絕策略

3.1 corePoolSize

當向線程池提交一個任務時,如果線程池中已創(chuàng)建的線程數(shù)量小于corePoolSIze,即便存在空閑線程,也會創(chuàng)建一個新線程來執(zhí)行任務,直到創(chuàng)建的線程數(shù)大于或等于corePoolSIze。

3.2 maximumPoolSize

線程池所允許的最大線程個數(shù),當隊列滿了且已經(jīng)創(chuàng)建的線程數(shù)小于maximumPoolSize時,會創(chuàng)建新的線程執(zhí)行任務。

3.3 keepAliveTime

當線程中的線程數(shù)大于corePoolSIze時,如果線程空閑時間大于keepAliveTime,該線程就會被銷毀。

3.4 unit

keepAliveTime的時間單位

3.5 workQueue

用于保存等待執(zhí)行任務的隊列

3.6 threadFactory

用于創(chuàng)建新線程。threadFactory創(chuàng)建的線程也是采用new Thread()方式,threadFactory創(chuàng)建的線程名都具有統(tǒng)一的風格:pool-m-thread-n

3.7 handler

拒絕策略,當線程池和隊列滿了之后,再加入新線程后會執(zhí)行此策略。 下面是四種線程池的拒絕策略:

AbortPolicy:中斷任務并拋出異常

DiscardPolicy:中段任務但是不拋出異常

DiscardOldestPolicy:丟棄隊列中最老的任務,然后嘗試提交新任務

CallerRunsPolicy:由調用線程處理該任務

(四)線程池執(zhí)行流程

當我們了解了ThreadPoolExecutor的七個參數(shù)后,我們就可以很快的理解線程池的流程:

線程池主要參數(shù)有哪些

當提交任務后,首先判斷當前線程數(shù)是否超過核心線程數(shù),如果沒超過則創(chuàng)建新線程執(zhí)行任務,否則判斷工作隊列是否已滿,如果未滿則將任務添加到隊列中,否則判斷線程數(shù)是否超過最大線程數(shù),如果未超過則創(chuàng)建線程執(zhí)行任務,否則執(zhí)行拒絕策略。

(五)Executors提供的線程池

executors提供了許多種線程池供用戶使用,雖然很多公司禁止使用executors創(chuàng)建線程池,但是對于剛開始解除線程池的人來說,Executors類所提供的線程池能很好的帶你進入多線程的世界。

5.1 newSingleThreadExecutor

ExecutorService executorService = Executors.newSingleThreadExecutor();

聽名字就可以知道這是一個單線程的線程池,在這個線程池中只有一個線程在工作,相當于單線程執(zhí)行所有任務,此線程可以保證所有任務的執(zhí)行順序按照提交順序執(zhí)行,看構造方法也可以看出,corePoolSize和maximumPoolSize都是1。

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

5.2 newFixedThreadPool

ExecutorService executorService = Executors.newFixedThreadPool(2);

固定長度的線程池,線程池的長度在創(chuàng)建時通過變量傳入。下面是newFixedThreadPool的構造方法,corePoolSize和maximumPoolSize都是傳入的參數(shù)值

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

5.3 newCachedThreadPool

ExecutorService executorService = Executors.newCachedThreadPool();

可緩存線程池,這個線程池設定keepAliveTime為60秒,并且對最大線程數(shù)量幾乎不做控制。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

觀察構造方法,corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即線程數(shù)量幾乎無限制。設定keepAliveTime 為60秒,線程空閑60秒后自動結束,因為該線程池創(chuàng)建無限制,不會有隊列等待,所以使用SynchronousQueue同步隊列。

5.4 newScheduledThreadPool

創(chuàng)建一個定時的線程池。此線程池支持定時以及周期性執(zhí)行任務的需求。下面是newScheduledThreadPool的用法:

Thread thread1=new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread1");
    }
});
Thread thread2=new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread2");
    }
});
Thread thread3=new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"thread3");
    }
});
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
//在1000ms后執(zhí)行thread1
scheduledExecutorService.schedule(thread1,1000,TimeUnit.MILLISECONDS);
//在1000ms后每隔1000ms執(zhí)行一次thread2,如果任務執(zhí)行時間比間隔時間長,則延遲執(zhí)行
scheduledExecutorService.scheduleAtFixedRate(thread2,1000,1000,TimeUnit.MILLISECONDS);
//和第二種方式類似,但下一次任務開始的時間為:上一次任務結束時間(而不是開始時間) + delay時間
scheduledExecutorService.scheduleWithFixedDelay(thread3,1000,1000,TimeUnit.MILLISECONDS);

(六)為什么阿里巴巴禁止程序員用Exectors創(chuàng)建線程池

如果你的idea裝了Alibaba Java Codeing Guidelines插件(推薦大家使用,有助于讓你的代碼更加規(guī)范),那么當你寫了Exectors創(chuàng)建線程池后會看到提示:

線程池主要參數(shù)有哪些

并且阿里將這個用法定義為Blocker,即不允許使用,而是讓人們用ThreadPoolExecutor的方式創(chuàng)建線程池。原因是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的人更加明確線程池的運行規(guī)則,規(guī)避資源耗盡的風險。

線程池主要參數(shù)有哪些

Executors返回的線程池對象的弊端如下:

1)FixedThreadPool和SingleThreadPool:

??允許的請求隊列長度為Integer.MAX_VALUE,可能會堆積大量的請求,從而導致OOM。 ?? 2)CachedThreadPool:

??允許的創(chuàng)建線程數(shù)量為Integer.MAX_VALUE,可能會創(chuàng)建大量的線程,從而導致OOM。 ?? 下面是ThreadPoolExecutor創(chuàng)建線程池的簡單例子

int corePoolSize=5;
int maximumPoolSize=10;
long keepAliveTime=30;
BlockingQueue<Runnable> blockingQueue=new ArrayBlockingQueue(2);
RejectedExecutionHandler handler=new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, blockingQueue, handler);
threadPoolExecutor.execute(thread1);

(七)在SpringBoot項目中使用線程池

SpringBoot對線程池又做了一層封裝,在SpringBoot中,可以通過ThreadPoolTaskExecutor類來創(chuàng)建線程池。需要注意兩者的區(qū)別ThreadPoolExecutor時JUC包下的類,ThreadPoolTaskExecutor是springframework包下的類。但原理都是一樣的。

7.1 項目搭建

首先搭建一個SpringBoot項目,只需要引入web依賴即可

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

7.2 配置文件配置

線程池的參數(shù)盡量寫到配置文件里,這樣就能根據(jù)需要進行修改,在application.properties文件中配置:

myExecutor.corePoolSize=5
myExecutor.maxPoolSize=10
myExecutor.keepAliveSeconds=30
myExecutor.allowCoreThreadTimeOut=false
myExecutor.queueCapacity=20
myExecutor.threadNamePrefix=myExecutor-

7.3 編寫一個自己的線程池

新建一個包叫config,新建類ExecutorConfig ,首先參數(shù)的值從配置文件中獲取,接著用ThreadPoolTaskExecutor 創(chuàng)建一個自己的線程池,注入到Bean容器中。

@Configuration
@EnableAsync
public class ExecutorConfig {

    @Value("${myExecutor.corePoolSize}")
    private int corePoolSize;
    @Value("${myExecutor.maxPoolSize}")
    private int maxPoolSize;
    @Value("${myExecutor.keepAliveSeconds}")
    private int keepAliveSeconds;
    @Value("${myExecutor.allowCoreThreadTimeOut}")
    private boolean allowCoreThreadTimeOut;
    @Value("${myExecutor.queueCapacity}")
    private int queueCapacity;
    @Value("${myExecutor.threadNamePrefix}")
    private String threadNamePrefix;

    @Bean("myExecutor")
    public Executor myExecutor(){
        ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
        //核心線程數(shù)
        executor.setCorePoolSize(corePoolSize);
        //最大線程數(shù)
        executor.setMaxPoolSize(maxPoolSize);
        //線程空閑時間
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //是否保留核心線程數(shù)
        executor.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);
        //隊列長度
        executor.setQueueCapacity(queueCapacity);
        //拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //設置線程名稱前綴
        executor.setThreadNamePrefix(threadNamePrefix);
        executor.initialize();
        return executor;
    }
}

這里需要注意的是有一個方法setAllowCoreThreadTimeOut,當傳入?yún)?shù)為true時,所有線程超時后都會被銷毀,如果為false,只有超過核心線程數(shù)并且超時時才會被銷毀。

7.4 編寫service并使用

首先寫一個service接口:

public interface DoSomeThing {
    /**
     * 通過線程池異步執(zhí)行耗時的任務
     */
    public void doSomeThing();
}

再編寫實現(xiàn)類:

@Service
public class DoSomeThingImpl implements DoSomeThing {

    @Override
    @Async("myExecutor")
    public void doSomeThing() {
        System.out.println(Thread.currentThread().getName()+"-in");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"-out");
    }
}

增加注解@Async("myExecutor")后,這段方法就會異步由myExecutor線程池執(zhí)行。

7.5 編寫一個controller

新建一個IndexController,每次請求執(zhí)行一次doSomeThing()方法。

@RestController
public class IndexController {

    @Autowired
    private DoSomeThing doSomeThing;

    @RequestMapping(value = "/index",method = RequestMethod.GET)
    public String index(){
        doSomeThing.doSomeThing();
        return "success";
    }
}

7.6 測試

訪問十次http://localhost:8080/index,由于設置的核心線程數(shù)是5,隊列容量是30,因此最多只會用到5個線程資源,結果如下:

線程池主要參數(shù)有哪些

到此,關于“線程池主要參數(shù)有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

當前文章:線程池主要參數(shù)有哪些
當前鏈接:http://www.muchs.cn/article42/jpcohc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設網(wǎng)站策劃、App設計用戶體驗網(wǎng)站設計公司、定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務器托管