真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java線程池的原理和應(yīng)用

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)java線程池的原理和應(yīng)用,以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

目前創(chuàng)新互聯(lián)公司已為上千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站托管維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、二道網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

線程池概述

1. 線程池就是一個(gè)管理線程的池子,可以降低創(chuàng)建和銷毀線程帶來的資源消耗

因?yàn)榫€程其實(shí)也是一個(gè)對(duì)象,創(chuàng)建一個(gè)對(duì)象,需要經(jīng)過類加載過程,銷毀一個(gè)對(duì)象,需要走GC垃圾回收流程,都是需要資源開銷的。

2. 提高響應(yīng)速度,任務(wù)到達(dá)了相對(duì)于從線程池取線程,自己創(chuàng)建線程肯定慢很多

3. 重復(fù)利用,線程用完了再放回池子,達(dá)到了重復(fù)利用的效果

線程池執(zhí)行

打個(gè)比喻

核心線程比作公司正式員工

非核心線程比作外包員工

阻塞隊(duì)列比作需求池

提交任務(wù)比作提需求

java線程池的原理和應(yīng)用

正式執(zhí)行

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,
   BlockingQueue workQueue,
   ThreadFactory threadFactory,
   RejectedExecutionHandler handler)
corePoolSize     核心線程數(shù)
maximumPoolSize  線程池最大線程數(shù)
keepAliveTime    空閑線程存活時(shí)間
TimeUnit         線程空閑存活時(shí)間單位
workQueue        存放任務(wù)的阻塞隊(duì)列
threadFactory    線程工廠
handler          飽和策略

● 提交一個(gè)任務(wù),線程池里存活的核心線程數(shù)小于線程數(shù)corePoolSize時(shí),線程池會(huì)創(chuàng)建一個(gè)核心線程去處理提交的任務(wù)。

● 如果線程池核心線程數(shù)已滿,即線程數(shù)已經(jīng)等于corePoolSize,一個(gè)新提交的任務(wù),會(huì)被放進(jìn)任務(wù)隊(duì)列workQueue排隊(duì)等待執(zhí)行。

● 當(dāng)線程池里面存活的線程數(shù)已經(jīng)等于corePoolSize了,并且任務(wù)隊(duì)列workQueue也滿,判斷線程數(shù)是否達(dá)到maximumPoolSize,即最大線程數(shù)是否已滿,如果沒到達(dá),創(chuàng)建一個(gè)非核心線程執(zhí)行提交的任務(wù)。

● 如果當(dāng)前的線程數(shù)達(dá)到了maximumPoolSize,還有新的任務(wù)過來的話,直接采用拒絕策略處理。

幾種飽和策略

AbortPolicy         拋出一個(gè)異常,默認(rèn)的
DiscardPolicy       直接丟棄任務(wù)
DiscardOldestPolicy 丟棄隊(duì)列里最老的任務(wù),將當(dāng)前這個(gè)任務(wù)繼續(xù)提交給線程池
CallerRunsPolicy    交給線程池調(diào)用所在的線程進(jìn)行處理

線程池異常處理

由于在線程池調(diào)用線程處理任務(wù)過程中出現(xiàn)的異??赡軙?huì)被線程池捕獲,所以對(duì)于任務(wù)的執(zhí)行可能是無感知的,因此我們需要考慮線程池異常情況。

方法一:

@Test
public void test1() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 5; i++) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("name: " + Thread.currentThread().getName());
                    Object a = null;
                    System.out.println(a.hashCode());
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
}

方法二:

@Test
public void test2() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 20; i++) {
        Future future = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("name: " + Thread.currentThread().getName());
                Object a = null;
                System.out.println(a.hashCode());
            }
        });
        try {
            future.get();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

線程池的工作隊(duì)列

● ArrayBlockingQueue

● LinkedBlockingQueue

● SynchronousQueue

● DelayQueue

● PriorityBlockingQueue

==ArrayBlockingQueue==

● 初始化一定容量的數(shù)組

● 使用一個(gè)重入鎖,默認(rèn)使用非公平鎖,入隊(duì)和出隊(duì)共用一個(gè)鎖,互斥

● 是有界設(shè)計(jì),如果容量滿無法繼續(xù)添加元素直至有元素被移除

● 使用時(shí)開辟一段連續(xù)的內(nèi)存,如果初始化容量過大容易造成資源浪費(fèi),過小易添加失敗

==LinkedBlockingQueue==

● 使用鏈表數(shù)據(jù)結(jié)構(gòu)

● 非連續(xù)性內(nèi)存空間

● 使用兩個(gè)重入鎖分別控制元素的入隊(duì)和出隊(duì),用Condition進(jìn)行線程間的喚醒和等待

● 有邊界的,在默認(rèn)構(gòu)造方法中容量是Integer.MAX_VALUE

==SynchronousQueue==

● 內(nèi)部容量是0

● 每次刪除操作都要等待插入操作

● 每次插入操作都要等待刪除操作

● 一個(gè)元素,一旦有了插入線程和移除線程,那么很快由插入線程移交給移除線程,這個(gè)容器相當(dāng)于通道,本身不存儲(chǔ)元素

● 在多任務(wù)隊(duì)列,是最快的處理任務(wù)方式。

==PriorityBlockingQueue==

● 無邊界設(shè)計(jì),但容量實(shí)際是依靠系統(tǒng)資源影響

● 添加元素,如果超過1,則進(jìn)入優(yōu)先級(jí)排序

==DelayQueue==

● 無邊界設(shè)計(jì)

● 添加(put)不阻塞,移除阻塞

● 元素都有一個(gè)過期時(shí)間

● 取元素只有過期的才會(huì)被取出

常用的線程池

● newFixedThreadPool (固定數(shù)目線程的線程池)

● newCachedThreadPool (可緩存線程的線程池)

● newSingleThreadExecutor (單線程的線程池)

● newScheduledThreadPool (定時(shí)及周期執(zhí)行的線程池)

==newFixedThreadPool==

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

特點(diǎn)

1. 核心線程數(shù)和最大線程數(shù)大小一樣

2. 沒有所謂的非空閑時(shí)間,即keepAliveTime為0

3. 阻塞隊(duì)列為無界隊(duì)列LinkedBlockingQueue

工作機(jī)制:

java線程池的原理和應(yīng)用

● 提交任務(wù)

● 如果線程數(shù)少于核心線程,創(chuàng)建核心線程執(zhí)行任務(wù)

● 如果線程數(shù)等于核心線程,把任務(wù)添加到LinkedBlockingQueue阻塞隊(duì)列

● 如果線程執(zhí)行完任務(wù),去阻塞隊(duì)列取任務(wù),繼續(xù)執(zhí)行。

==newCachedThreadPool==

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

線程池特點(diǎn)

● 核心線程數(shù)為0

● 最大線程數(shù)為Integer.MAX_VALUE

● 阻塞隊(duì)列是SynchronousQueue

● 非核心線程空閑存活時(shí)間為60秒

java線程池的原理和應(yīng)用

工作機(jī)制:

● 提交任務(wù)

● 因?yàn)闆]有核心線程,所以任務(wù)直接加到SynchronousQueue隊(duì)列。

● 判斷是否有空閑線程,如果有,就去取出任務(wù)執(zhí)行。

● 如果沒有空閑線程,就新建一個(gè)線程執(zhí)行。

● 執(zhí)行完任務(wù)的線程,還可以存活60秒,如果在這期間,接到任務(wù),可以繼續(xù)活下去;否則,被銷毀。

使用場景

用于并發(fā)執(zhí)行大量短期的小任務(wù)。

使用SynchronousQueue作為工作隊(duì)列,工作隊(duì)列本身并不限制待執(zhí)行的任務(wù)的數(shù)量。但此時(shí)需要限定線程池的最大大小為一個(gè)合理的有限值,而不是Integer.MAX_VALUE,否則可能導(dǎo)致線程池中的工作者線程的數(shù)量一直增加到系統(tǒng)資源所無法承受為止。

如果應(yīng)用程序確實(shí)需要比較大的工作隊(duì)列容量,而又想避免無界工作隊(duì)列可能導(dǎo)致的問題,不妨考慮SynchronousQueue。SynchronousQueue實(shí)現(xiàn)上并不使用緩存空間

==newSingleThreadExecutor==

線程池特點(diǎn)

● 核心線程數(shù)為1

● 最大線程數(shù)也為1

● 阻塞隊(duì)列是LinkedBlockingQueue

● keepAliveTime為0

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

工作機(jī)制

java線程池的原理和應(yīng)用

● 提交任務(wù)

● 線程池是否有一條線程在,如果沒有,新建線程執(zhí)行任務(wù)

● 如果有,講任務(wù)加到阻塞隊(duì)列

● 當(dāng)前的唯一線程,從隊(duì)列取任務(wù),執(zhí)行完一個(gè),再繼續(xù)取,一個(gè)人(一條線程)夜以繼日地干活。

使用場景

適用于串行執(zhí)行任務(wù)的場景,一個(gè)任務(wù)一個(gè)任務(wù)的執(zhí)行

==newScheduledThreadPool==

線程池特點(diǎn)

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());
}

● 最大線程數(shù)為Integer.MAX_VALUE

● 阻塞隊(duì)列是DelayedWorkQueue

● keepAliveTime為0

● scheduleAtFixedRate() :按某種速率周期執(zhí)行

● scheduleWithFixedDelay():在某個(gè)延遲后執(zhí)行

工作機(jī)制

● 添加一個(gè)任務(wù)

● 線程池中的線程從 DelayQueue 中取任務(wù)

● 線程從 DelayQueue 中獲取 time 大于等于當(dāng)前時(shí)間的task

● 執(zhí)行完后修改這個(gè) task 的 time 為下次被執(zhí)行的時(shí)間

● 這個(gè) task 放回DelayQueue隊(duì)列中

scheduleWithFixedDelay

● 無論任務(wù)執(zhí)行時(shí)間長短,都是當(dāng)?shù)谝粋€(gè)任務(wù)執(zhí)行完成之后,延遲指定時(shí)間再開始執(zhí)行第二個(gè)任務(wù)

scheduleAtFixedRate

● 在任務(wù)執(zhí)行時(shí)間小于間隔時(shí)間的情況下,程序以起始時(shí)間為準(zhǔn)則,每隔指定時(shí)間執(zhí)行一次,不受任務(wù)執(zhí)行時(shí)間影響

● 當(dāng)執(zhí)行任務(wù)時(shí)間大于間隔時(shí)間,此方法不會(huì)重新開啟一個(gè)新的任務(wù)進(jìn)行執(zhí)行,而是等待原有任務(wù)執(zhí)行完成,馬上開啟下一個(gè)任務(wù)進(jìn)行執(zhí)行。此時(shí),執(zhí)行間隔時(shí)間已經(jīng)被打亂

上述就是小編為大家分享的java線程池的原理和應(yīng)用了,如果您也有類似的疑惑,不妨參照上述方法進(jìn)行嘗試。如果想了解更多相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊。


網(wǎng)站題目:java線程池的原理和應(yīng)用
分享地址:http://weahome.cn/article/pgjgph.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部