欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中該如何優(yōu)雅的使用線程池詳解

 更新時間:2021年12月15日 09:10:02   作者:細(xì)思極恐  
在java開發(fā)中我們對“池”的概念并不陌生,常見的有數(shù)據(jù)庫連接池、線程池、對象池、常量池等等,其作用基本上就是避免頻繁的創(chuàng)建和回收,造成資源浪費(fèi),線程池也不例外,這篇文章主要給大家介紹了關(guān)于Java中該如何優(yōu)雅的使用線程池的相關(guān)資料,需要的朋友可以參考下

為什么要用線程池?

線程是不是越多越好?

  1. 線程在java中是一個對象,更是操作系統(tǒng)的資源,線程創(chuàng)建、銷毀需要時間。如果創(chuàng)建時間+小會時間>執(zhí)行任務(wù)時間就很不合算。
  2. java對象占用堆內(nèi)存,操作系統(tǒng)線程占用系統(tǒng)內(nèi)存,根據(jù)jvm規(guī)范,一個線程默認(rèn)最大棧大小1M,這個??臻g是需要從系統(tǒng)內(nèi)存中分配的。線程過多,會消耗很多的內(nèi)存。
  3. 操作系統(tǒng)需要頻繁切換線程上下文(每個線都想被運(yùn)行),影響性能。

線程池的推出,就是為了方便邊的控制線程數(shù)量。

線程池

線程池基本概念

線程池包括以下四個基本組成部分:

  1. 線程池管理器:用于創(chuàng)建并管理線程池,包括創(chuàng)建線程池,銷毀線程池,添加新任務(wù);
  2. 工作線程:線程池中線程,在沒有任務(wù)時處于等待狀態(tài),可以循環(huán)的執(zhí)行任務(wù);
  3. 任務(wù)接口:每個任務(wù)必須實現(xiàn)的借口,以供工作線程調(diào)度任務(wù)的執(zhí)行,它主要規(guī)定了任務(wù)的入口,任務(wù)執(zhí)行完后的收尾工作,任務(wù)的執(zhí)行狀態(tài)等;
  4. 任務(wù)隊列:用于存放沒有處理的任務(wù)。提供一種緩沖機(jī)制。

線程池接口定義和實現(xiàn)類

可以認(rèn)為ScheduledThreadPoolExector是最豐富的實現(xiàn)類。

ExecutorService

public interface ExecutorService extends Executor {
    /**
     * 優(yōu)雅關(guān)閉線程池,之前提交的任務(wù)將被執(zhí)行,但是不會接受新的任務(wù)。
     */
    void shutdown();

    /**
     * 嘗試停止所有正在執(zhí)行的任務(wù),停止等待任務(wù)的處理,并返回等待執(zhí)行任務(wù)的列表。
     */
    List<Runnable> shutdownNow();

    /**
     * 如果此線程池已關(guān)閉,則返回true.
     */
    boolean isShutdown();

    /**
     * 如果關(guān)閉后的所有任務(wù)都已完成,則返回true
     */
    boolean isTerminated();

    /**
     * 監(jiān)測ExecutorService是否已經(jīng)關(guān)閉,直到所有任務(wù)完成執(zhí)行,或超時發(fā)生,或當(dāng)前線程被中斷。
     */
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 提交一個用于執(zhí)行的Callable返回任務(wù),并返回一個Future,用于獲取Callable執(zhí)行結(jié)果。
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * 提交可運(yùn)行任務(wù)以執(zhí)行,并返回Future,執(zhí)行結(jié)果為傳入的result
     */
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 提交可運(yùn)行任務(wù)以執(zhí)行,并返回Future對象,執(zhí)行結(jié)果為null
     */
    Future<?> submit(Runnable task);

    /**
     * 執(zhí)行給定的任務(wù)集合,執(zhí)行完畢后,則返回結(jié)果。
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

    /**
     * 執(zhí)行給定的任務(wù)集合,執(zhí)行完畢或者超時后,則返回結(jié)果,其他任務(wù)終止。
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 執(zhí)行給定的任務(wù),任意一個執(zhí)行成功則返回結(jié)果,其他任務(wù)終止。
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;

    /**
     * 執(zhí)行給定的任務(wù),任意一個執(zhí)行成功或者超時后,則返回結(jié)果,其他任務(wù)終止
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
}

ScheduledExecutorService

public interface ScheduledExecutorService extends ExecutorService {

    /**
     * 創(chuàng)建并執(zhí)行一個一次性任務(wù),過了延遲時間就會被執(zhí)行
     */
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);

    /**
     * 創(chuàng)建并執(zhí)行一個一次性任務(wù),過了延遲時間就會被執(zhí)行
     */
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);

    /**
     * 創(chuàng)建并執(zhí)行一個周期性任務(wù),過了給定的初始化延遲時間,會第一次被執(zhí)行。執(zhí)行過程中發(fā)生了異常,那么任務(wù)停止
     * 一次任務(wù)執(zhí)行時長超過了周期時間,下一次任務(wù)會等到該次任務(wù)執(zhí)行結(jié)束后,立刻執(zhí)行,這也是它和scheduleWithTixedDelay的重要區(qū)別
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

    /**
     * 創(chuàng)建并執(zhí)行一個周期性任務(wù),過了給定的初始化延遲時間,會第一次被執(zhí)行。執(zhí)行過程中發(fā)生了異常,那么任務(wù)停止
     * 一次任務(wù)執(zhí)行時長超過了周期時間,下一次任務(wù)會在該次任務(wù)執(zhí)行結(jié)束的時間基礎(chǔ)上,計算執(zhí)行延時。
     * 對于超時周期的長時間處理任務(wù)的不同處理方式,這是它和scheduleAtFixedRate的重要區(qū)別
     */
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

}

線程池工具類

在使用過程中,可以自己實例化線程池,也可以用Executors創(chuàng)建線程池的工廠累,常用方法如下:

newFixedThreadPool(int nThreads)

創(chuàng)建一個固定大小、任務(wù)隊列容量誤解的線程池。核心線程數(shù)=最大線程數(shù)。

newCachedThreadPool()

創(chuàng)建的是一個大小無界的緩沖線程池。它的任務(wù)隊列是一個同步隊列。任務(wù)加入到池中,如果池中有空閑線程,則用空閑線程執(zhí)行,如無則創(chuàng)建新線程執(zhí)行。池中的線程空閑時間超過60秒,將被銷毀釋放。線程數(shù)隨任務(wù)的多少變化。適用于執(zhí)行耗時較小的異步任務(wù)。池的核心線程數(shù)=0,最大線程=Integer.MAX_VALUE

newSingleThreadExecutor()

只有一個線程來執(zhí)行無界任務(wù)隊列的單一線程池。該線程池確保任務(wù)加入的順序一個一個一次執(zhí)行。當(dāng)唯一的線程因任務(wù)異常中止時,將創(chuàng)建一個新的線程來繼續(xù)執(zhí)行后續(xù)的任務(wù)。與newFixedThreadPool(1)的區(qū)別在于,單一線程池的池大小在newSingleThreadExecutor方法中硬編碼,不能再改變的。

newScheduledThreadPool(int corePoolSize)

能定時執(zhí)行任務(wù)的線程池。該池的核心線程數(shù)由參數(shù)指定,最大線程數(shù)=Integer.MAX_VALUE

任務(wù)線程池執(zhí)行過程

如何確認(rèn)合適的線程數(shù)量?

  • 如果是CPU密集型應(yīng)用,則線程池大小設(shè)置為N+1 (N為CPU總核數(shù))
  • 如果是IO密集型應(yīng)用,則線程池大小設(shè)置為2N+1 (N為CPU總核數(shù))
  • 線程等待時間(IO)所占比例越高,需要越多線程。
  • 線程CPU時間所占比例越高,需要越少線程。

一個系統(tǒng)最快的部分是CPU,所以決定一個系統(tǒng)吞吐量上限的是CPU。增強(qiáng)CPU處理能力,可以提高系統(tǒng)吞吐量上限。但根據(jù)短板效應(yīng),真實的系統(tǒng)吞吐量并不能單純根據(jù)CPU來計算。那要提高系統(tǒng)吞吐量,就需要從“系統(tǒng)短板”(比如網(wǎng)絡(luò)延遲、IO)著手:

  1. 盡量提高短板操作的并行化比率,比如多線程下載技術(shù);
  2. 增強(qiáng)短板能力,比如用NIO替代IO;

線程池的使用分析

public class ExecutorsUse {
    /**
     * 測試: 提交15 個執(zhí)行時間需要3秒的任務(wù),看線程池的狀況
     *
     * @param threadPoolExecutor 傳入不同的線程池,看不同的結(jié)果
     * @throws Exception
     */
    public void testCommon(ThreadPoolExecutor threadPoolExecutor) throws Exception {
        // 測試: 提交15個執(zhí)行時間需要3秒的任務(wù),看超過大小的2個,對應(yīng)的處理情況
        for (int i = 0; i < 15; i++) {
            int n = i;
            threadPoolExecutor.submit(() -> {
                        try {
                            System.out.println("開始執(zhí)行:" + n);
                            Thread.sleep(3000L);
                            System.err.println("執(zhí)行結(jié)束:" + n);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
            );
            System.out.println("任務(wù)提交成功 :" + i);
        }
        // 查看線程數(shù)量,查看隊列等待數(shù)量
        Thread.sleep(500L);
        System.out.println("當(dāng)前線程池線程數(shù)量為:" + threadPoolExecutor.getPoolSize());
        System.out.println("當(dāng)前線程池等待的數(shù)量為:" + threadPoolExecutor.getQueue().size());
        // 等待15秒,查看線程數(shù)量和隊列數(shù)量(理論上,會被超出核心線程數(shù)量的線程自動銷毀)
        Thread.sleep(15000L);
        System.out.println("當(dāng)前線程池線程數(shù)量為:" + threadPoolExecutor.getPoolSize());
        System.out.println("當(dāng)前線程池等待的數(shù)量為:" + threadPoolExecutor.getQueue().size());
    }

    /**
     * 1、線程池信息: 核心線程數(shù)量5,最大數(shù)量10,無界隊列,超出核心線程數(shù)量的線程存活時間:5秒, 指定拒絕策略
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest1() throws Exception {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>());
        testCommon(threadPoolExecutor);
        // 預(yù)計結(jié)果:線程池線程數(shù)量為:5,超出數(shù)量的任務(wù),其他的進(jìn)入隊列中等待被執(zhí)行
    }

    /**
     * 2、 線程池信息: 核心線程數(shù)量5,最大數(shù)量10,隊列大小3,超出核心線程數(shù)量的線程存活時間:5秒, 指定拒絕策略的
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest2() throws Exception {
        // 創(chuàng)建一個 核心線程數(shù)量為5,最大數(shù)量為10,等待隊列最大是3 的線程池,也就是最大容納13個任務(wù)。
        // 默認(rèn)的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(3), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.err.println("有任務(wù)被拒絕執(zhí)行了");
            }
        });
        testCommon(threadPoolExecutor);
        // 預(yù)計結(jié)果:
        // 1、 5個任務(wù)直接分配線程開始執(zhí)行
        // 2、 3個任務(wù)進(jìn)入等待隊列
        // 3、 隊列不夠用,臨時加開5個線程來執(zhí)行任務(wù)(5秒沒活干就銷毀)
        // 4、 隊列和線程池都滿了,剩下2個任務(wù),沒資源了,被拒絕執(zhí)行。
        // 5、 任務(wù)執(zhí)行,5秒后,如果無任務(wù)可執(zhí)行,銷毀臨時創(chuàng)建的5個線程
    }

    /**
     * 3、 線程池信息: 核心線程數(shù)量5,最大數(shù)量5,無界隊列,超出核心線程數(shù)量的線程存活時間:5秒
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest3() throws Exception {
        // 和Executors.newFixedThreadPool(int nThreads)一樣的
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        testCommon(threadPoolExecutor);
        // 預(yù)計結(jié):線程池線程數(shù)量為:5,超出數(shù)量的任務(wù),其他的進(jìn)入隊列中等待被執(zhí)行
    }

    /**
     * 4、 線程池信息:
     * 核心線程數(shù)量0,最大數(shù)量Integer.MAX_VALUE,SynchronousQueue隊列,超出核心線程數(shù)量的線程存活時間:60秒
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest4() throws Exception {

        // SynchronousQueue,實際上它不是一個真正的隊列,因為它不會為隊列中元素維護(hù)存儲空間。與其他隊列不同的是,它維護(hù)一組線程,這些線程在等待著把元素加入或移出隊列。
        // 在使用SynchronousQueue作為工作隊列的前提下,客戶端代碼向線程池提交任務(wù)時,
        // 而線程池中又沒有空閑的線程能夠從SynchronousQueue隊列實例中取一個任務(wù),
        // 那么相應(yīng)的offer方法調(diào)用就會失?。慈蝿?wù)沒有被存入工作隊列)。
        // 此時,ThreadPoolExecutor會新建一個新的工作者線程用于對這個入隊列失敗的任務(wù)進(jìn)行處理(假設(shè)此時線程池的大小還未達(dá)到其最大線程池大小maximumPoolSize)。

        // 和Executors.newCachedThreadPool()一樣的
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());
        testCommon(threadPoolExecutor);
        // 預(yù)計結(jié)果:
        // 1、 線程池線程數(shù)量為:15,超出數(shù)量的任務(wù),其他的進(jìn)入隊列中等待被執(zhí)行
        // 2、 所有任務(wù)執(zhí)行結(jié)束,60秒后,如果無任務(wù)可執(zhí)行,所有線程全部被銷毀,池的大小恢復(fù)為0
        Thread.sleep(60000L);
        System.out.println("60秒后,再看線程池中的數(shù)量:" + threadPoolExecutor.getPoolSize());
    }

    /**
     * 5、 定時執(zhí)行線程池信息:3秒后執(zhí)行,一次性任務(wù),到點(diǎn)就執(zhí)行 <br/>
     * 核心線程數(shù)量5,最大數(shù)量Integer.MAX_VALUE,DelayedWorkQueue延時隊列,超出核心線程數(shù)量的線程存活時間:0秒
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest5() throws Exception {
        // 和Executors.newScheduledThreadPool()一樣的
        ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(5);
        threadPoolExecutor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("任務(wù)被執(zhí)行,現(xiàn)在時間:" + System.currentTimeMillis());
            }
        }, 3000, TimeUnit.MILLISECONDS);
        System.out.println(
                "定時任務(wù),提交成功,時間是:" + System.currentTimeMillis() + ", 當(dāng)前線程池中線程數(shù)量:" + threadPoolExecutor.getPoolSize());
        // 預(yù)計結(jié)果:任務(wù)在3秒后被執(zhí)行一次
    }

    /**
     * 6、 定時執(zhí)行線程池信息:線程固定數(shù)量5 ,<br/>
     * 核心線程數(shù)量5,最大數(shù)量Integer.MAX_VALUE,DelayedWorkQueue延時隊列,超出核心線程數(shù)量的線程存活時間:0秒
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest6() throws Exception {
        ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(5);
        // 周期性執(zhí)行某一個任務(wù),線程池提供了兩種調(diào)度方式,這里單獨(dú)演示一下。測試場景一樣。
        // 測試場景:提交的任務(wù)需要3秒才能執(zhí)行完畢??磧煞N不同調(diào)度方式的區(qū)別
        // 效果1: 提交后,2秒后開始第一次執(zhí)行,之后每間隔1秒,固定執(zhí)行一次(如果發(fā)現(xiàn)上次執(zhí)行還未完畢,則等待完畢,完畢后立刻執(zhí)行)。
        // 也就是說這個代碼中是,3秒鐘執(zhí)行一次(計算方式:每次執(zhí)行三秒,間隔時間1秒,執(zhí)行結(jié)束后馬上開始下一次執(zhí)行,無需等待)
        threadPoolExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任務(wù)-1 被執(zhí)行,現(xiàn)在時間:" + System.currentTimeMillis());
            }
        }, 2000, 1000, TimeUnit.MILLISECONDS);

        // 效果2:提交后,2秒后開始第一次執(zhí)行,之后每間隔1秒,固定執(zhí)行一次(如果發(fā)現(xiàn)上次執(zhí)行還未完畢,則等待完畢,等上一次執(zhí)行完畢后再開始計時,等待1秒)。
        // 也就是說這個代碼鐘的效果看到的是:4秒執(zhí)行一次。 (計算方式:每次執(zhí)行3秒,間隔時間1秒,執(zhí)行完以后再等待1秒,所以是 3+1)
        threadPoolExecutor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任務(wù)-2 被執(zhí)行,現(xiàn)在時間:" + System.currentTimeMillis());
            }
        }, 2000, 1000, TimeUnit.MILLISECONDS);
    }

    /**
     * 7、 終止線程:線程池信息: 核心線程數(shù)量5,最大數(shù)量10,隊列大小3,超出核心線程數(shù)量的線程存活時間:5秒, 指定拒絕策略的
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest7() throws Exception {
        // 創(chuàng)建一個 核心線程數(shù)量為5,最大數(shù)量為10,等待隊列最大是3 的線程池,也就是最大容納13個任務(wù)。
        // 默認(rèn)的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(3), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.err.println("有任務(wù)被拒絕執(zhí)行了");
            }
        });
        // 測試: 提交15個執(zhí)行時間需要3秒的任務(wù),看超過大小的2個,對應(yīng)的處理情況
        for (int i = 0; i < 15; i++) {
            int n = i;
            threadPoolExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("開始執(zhí)行:" + n);
                        Thread.sleep(3000L);
                        System.err.println("執(zhí)行結(jié)束:" + n);
                    } catch (InterruptedException e) {
                        System.out.println("異常:" + e.getMessage());
                    }
                }
            });
            System.out.println("任務(wù)提交成功 :" + i);
        }
        // 1秒后終止線程池
        Thread.sleep(1000L);
        threadPoolExecutor.shutdown();
        // 再次提交提示失敗
        threadPoolExecutor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("追加一個任務(wù)");
            }
        });
        // 結(jié)果分析
        // 1、 10個任務(wù)被執(zhí)行,3個任務(wù)進(jìn)入隊列等待,2個任務(wù)被拒絕執(zhí)行
        // 2、調(diào)用shutdown后,不接收新的任務(wù),等待13任務(wù)執(zhí)行結(jié)束
        // 3、 追加的任務(wù)在線程池關(guān)閉后,無法再提交,會被拒絕執(zhí)行
    }

    /**
     * 8、 立刻終止線程:線程池信息: 核心線程數(shù)量5,最大數(shù)量10,隊列大小3,超出核心線程數(shù)量的線程存活時間:5秒, 指定拒絕策略的
     *
     * @throws Exception
     */
    private void threadPoolExecutorTest8() throws Exception {
        // 創(chuàng)建一個 核心線程數(shù)量為5,最大數(shù)量為10,等待隊列最大是3 的線程池,也就是最大容納13個任務(wù)。
        // 默認(rèn)的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(3), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.err.println("有任務(wù)被拒絕執(zhí)行了");
            }
        });
        // 測試: 提交15個執(zhí)行時間需要3秒的任務(wù),看超過大小的2個,對應(yīng)的處理情況
        for (int i = 0; i < 15; i++) {
            int n = i;
            threadPoolExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("開始執(zhí)行:" + n);
                        Thread.sleep(3000L);
                        System.err.println("執(zhí)行結(jié)束:" + n);
                    } catch (InterruptedException e) {
                        System.out.println("異常:" + e.getMessage());
                    }
                }
            });
            System.out.println("任務(wù)提交成功 :" + i);
        }
        // 1秒后終止線程池
        Thread.sleep(1000L);
        List<Runnable> shutdownNow = threadPoolExecutor.shutdownNow();
        // 再次提交提示失敗
        threadPoolExecutor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("追加一個任務(wù)");
            }
        });
        System.out.println("未結(jié)束的任務(wù)有:" + shutdownNow.size());

        // 結(jié)果分析
        // 1、 10個任務(wù)被執(zhí)行,3個任務(wù)進(jìn)入隊列等待,2個任務(wù)被拒絕執(zhí)行
        // 2、調(diào)用shutdownnow后,隊列中的3個線程不再執(zhí)行,10個線程被終止
        // 3、 追加的任務(wù)在線程池關(guān)閉后,無法再提交,會被拒絕執(zhí)行
    }

    public static void main(String[] args) throws Exception {
//        new ExecutorsUse().threadPoolExecutorTest1();
//        new ExecutorsUse().threadPoolExecutorTest2();
//          new ExecutorsUse().threadPoolExecutorTest3();
        new ExecutorsUse().threadPoolExecutorTest4();
//        new ExecutorsUse().threadPoolExecutorTest5();
//        new ExecutorsUse().threadPoolExecutorTest6();
//        new ExecutorsUse().threadPoolExecutorTest7();
//        new ExecutorsUse().threadPoolExecutorTest8();
    }
}

合理配置線程池大小

如果想合理設(shè)置線程池的線程數(shù)量需要考慮兩個問題:

1、需要分析線程池執(zhí)行的任務(wù)的特性: CPU 密集型還是 IO 密集型。

2、每個任務(wù)執(zhí)行的平均時長大概是多少,這個任務(wù)的執(zhí)行時長可能還跟任務(wù)處理邏輯是否涉及到網(wǎng)絡(luò)傳輸以及底層系統(tǒng)資源依賴有關(guān)系。

如果是 CPU 密集型,那線程池的最大線程數(shù)可以配置為 cpu 核心數(shù)+1;如果是 IO 密集型,線程池設(shè)定最佳線程數(shù)目 = ((線程池設(shè)定的線程等待時間+線程 CPU 時間)/線程 CPU 時間 )* CPU 數(shù)目。

線程池的關(guān)閉

ThreadPoolExecutor 提供了兩個方法 ,用于線程池的關(guān)閉 ,分 別 是 shutdown() 和shutdownNow(),其中:shutdown():不會立即終止線程池,而是要等所有任務(wù)緩存隊列中的任務(wù)都執(zhí)行完后才終止,但再也不會接受新的任務(wù) shutdownNow():立即終止線程池,并嘗試打斷正在執(zhí)行的任務(wù),并且清空任務(wù)緩存隊列,返回尚未執(zhí)行的任務(wù)。

總結(jié)

到此這篇關(guān)于Java中該如何優(yōu)雅的使用線程池的文章就介紹到這了,更多相關(guān)Java優(yōu)雅使用線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java語言實現(xiàn)猜數(shù)字游戲

    java語言實現(xiàn)猜數(shù)字游戲

    這篇文章主要為大家詳細(xì)介紹了java語言實現(xiàn)猜數(shù)字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • 關(guān)于springboot使用rocketmq?RocketMQMessageListener參數(shù)問題

    關(guān)于springboot使用rocketmq?RocketMQMessageListener參數(shù)問題

    這篇文章主要介紹了springboot使用rocketmq?RocketMQMessageListener參數(shù)問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值需要的朋友可以參考下
    2022-11-11
  • Java陷阱之a(chǎn)ssert關(guān)鍵字詳解

    Java陷阱之a(chǎn)ssert關(guān)鍵字詳解

    這篇文章詳細(xì)介紹了Java陷阱之a(chǎn)ssert關(guān)鍵字,有需要的朋友可以參考一下
    2013-09-09
  • 一文搞懂java中的棧和括號匹配

    一文搞懂java中的棧和括號匹配

    棧在我們?nèi)粘>幋a中遇到的非常多,很多人對棧的接觸可能僅僅局限在?遞歸使用的棧?和?StackOverflowException,棧是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)(可以想象生化金字塔的牢房和生化角斗場的狗洞)
    2023-11-11
  • SpringBoot中的共享Session域詳解

    SpringBoot中的共享Session域詳解

    這篇文章主要介紹了SpringBoot中的共享Session域詳解,使用Redis解決Session共享問題的原理非常簡單,就是把原本存儲在不同服務(wù)器上的Session拿出來放在一個獨(dú)立的服務(wù)器上,需要的朋友可以參考下
    2024-01-01
  • 一文徹底了解Java的組合模式

    一文徹底了解Java的組合模式

    組合模式(Composite?Pattern)指將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),?使得用戶對單個對象和組合對象的使用具有一致性。本文就來帶大家深入了解一下Java的組合模式吧
    2023-02-02
  • Java?在游戲中探索數(shù)組二維數(shù)組

    Java?在游戲中探索數(shù)組二維數(shù)組

    數(shù)組和二維數(shù)組感覺用王者榮耀的裝備欄來舉例解釋,應(yīng)該更易懂一些。從基礎(chǔ)開始講,后續(xù)會講到JAVA高級,中間會穿插面試題和項目實戰(zhàn),希望能給大家?guī)韼椭?/div> 2022-03-03
  • Java?Process中waitFor()的問題詳解

    Java?Process中waitFor()的問題詳解

    這篇文章主要給大家介紹了關(guān)于Java?Process中waitFor()問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-12-12
  • Java中獲取鍵盤輸入值的三種方法介紹

    Java中獲取鍵盤輸入值的三種方法介紹

    這篇文章主要介紹了Java中獲取鍵盤輸入值的三種方法介紹,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java classloader和namespace詳細(xì)介紹

    Java classloader和namespace詳細(xì)介紹

    這篇文章主要介紹了Java classloader和namespace詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評論