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

Java線程池由淺入深掌握到精通

 更新時間:2021年09月30日 16:02:23   作者:白楊學編程  
什么是線程池?很簡單,簡單看名字就知道是裝有線程的池子,我們可以把要執(zhí)行的多線程交給線程池來處理,和連接池的概念一樣,通過維護一定數(shù)量的線程池來達到多個線程的復用

1.為什么使用線程池?

反復創(chuàng)建線程開銷大,可以復用線程池
過多的線程會占用太多的內(nèi)存

解決以上問題的方法:

  • 用少量的線程,避免內(nèi)存占用過多
  • 讓這部分線程都保持工作,且反復執(zhí)行任務,避免生命周期的損耗

2.線程池的好處:

加快響應速度,提高用戶體驗
合理利用CPU內(nèi)存
統(tǒng)一管理

3.線程池使用的場合

服務器接受大量請求時,使用線程池技術(shù)是非常合適的,它可以大大減少線程的創(chuàng)建和銷毀次數(shù),提高服務器的工作效率。在實際開發(fā)中,如果創(chuàng)建5個以上 的線程,那么就可以使用線程池來管理線程。

4.創(chuàng)建和停止線程

線程池構(gòu)造方法的參數(shù)?
線程池應該手動創(chuàng)建和自動創(chuàng)建那個更好?
線程池里的線程數(shù)量設置未多少合適?
停止線程的正確方法?

線程池構(gòu)造函數(shù)的參數(shù):

線程池構(gòu)造函數(shù)的參數(shù)

corePoolSize: 核心線程數(shù)
線程池在完成初始化后,默認情況下,線程池中并沒有任何線程,會等到有任務到來時再去創(chuàng)建新的線程去執(zhí)行任務。
maxPoolSize:在核心線程的基礎(chǔ)上,額外增加的線程數(shù)的上限。

在這里插入圖片描述

根據(jù)圖可知添加線程的規(guī)則:

1.如果線程數(shù)小于corePoolSize,即使其他工作線程處于空閑狀態(tài),也會創(chuàng)建一個新線程來運行任務。
2.如果線程數(shù)等于或大于corePoolSize但少于maximumPoolSize,則將任務放入隊列。
3.如果線程池已滿,并且線程數(shù)小于maxPoolSize,則創(chuàng)建一個新線程來運行任務。
4.如果隊列已滿,并且線程數(shù)大于或等于maxPoolSzie,則參數(shù)拒絕該任務。

添加線程規(guī)則

添加線程判斷順序:corePoolSize——workQueue——maxPoolSize

比如線程池的核心線程是5個,最大線程池大小為10個,隊列為50個。
則線程池的請求最多會創(chuàng)建5個,然后任務將被添加到隊列中,直到達到50。隊列已滿時,將創(chuàng)建最新的線程maxPoolSize,最多達到10個,如果再來任務就直接拒絕。

keepAliveTime:如果線程池當前的線程數(shù)多于corePoolSize,那么如果多余的線程空閑時間超過keepAliveTime,那么就會終止。

ThreadFactory:
默認使用Executors.defaultThreadFactory()
創(chuàng)建出來的線程都在同一個線程組。
如果自己指定ThreadFactory,那么就可以改變線程名、線程組、優(yōu)先級、是否是守護線程等等。

常見的3中隊列類型:
直接交接:SynchronousQueue
無界隊列:LinkedBlockingQueue
有界隊列:ArrayBlockingQueue

線程池應該手動創(chuàng)建和自動創(chuàng)建那個更好?

手動創(chuàng)建好,因為這樣可以明確線程池的運行規(guī)則和避開資源浪費的風險。

  • newFixedThreadPool:容易造成大量內(nèi)存占用,可能導致DOM
    public class FixedThreadPoolTest  {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            for (int i = 0; i < 500; i++) {
                executorService.execute(new Task());
            }
        }
    }
    class Task implements Runnable{
    
        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
    
  • newSingleThreadExecutor:當請求堆積的時候,可能會占用大量內(nèi)存。
    //演示FixedThreadPool出錯
    public class FixedThreadPoolOOM {
        private static ExecutorService executorService = Executors.newFixedThreadPool(1);
    
        public static void main(String[] args) {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                executorService.execute(new SubThread());
            }
        }
    }
    class SubThread implements Runnable{
    
        @Override
        public void run() {
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
  • newCachedThreadPool:弊端在于第二個參數(shù)maximumPoolSize被設置為了Integer.MAX_VALUE,這可能會創(chuàng)建數(shù)量非常多的線程,甚至導致DOM
  • newScheduledThreadPool:原因和newCachedThreadPool一樣

常見的線程池:

FixedThreadPool

在這里插入圖片描述

CachedThreadPool:可緩存線程池,具有自動回收多余線程的功能

在這里插入圖片描述

ScheduledThreadPool:支持定時及周期性任務執(zhí)行的線程池
SingleThreadExecutor:單線程的線程池只會用唯一的工作線程來執(zhí)行任務
原理和FixedThreadPool一樣,但是線程數(shù)量被設為1

四種線程池的構(gòu)造方法的參數(shù):

在這里插入圖片描述

阻塞隊列分析:

在這里插入圖片描述

5.停止線程池的方法

  • shutdown:只是將線程池的狀態(tài)設置為 shutdown 狀態(tài),但任務并沒有中斷,還是會繼續(xù)執(zhí)行下去。此時線程池不會接受新的任務,只是將原有的任務執(zhí)行結(jié)束。
  • shutdownNow:將線程池的狀態(tài)設置為STOP,正在執(zhí)行的任務會停止,沒被執(zhí)行的任務會被返回。
  • isShutdown:當調(diào)用shutdown()或shutdownNow()方法后返回為true,否則返回為false。
  • isTerminated:線程任務全部執(zhí)行完返回true
  • awaitTerminated:有兩個參數(shù),第一個是long類型的數(shù)值,第二個是時間類型TimeUnit,用于設置阻塞時間。它是一個阻塞的方法,若線程池一直運行則會一直阻塞,直到線程池關(guān)閉返回true,或阻塞時間超過你設置的這個時間,則返回false。此方法必須放在shutdown()方法之后,否則一直在阻塞,或超過設置的阻塞時間返回false。
//演示關(guān)閉線程池
public class ShutDown {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 500; i++) {
            executorService.execute(new ShutDownTask());
        }
        Thread.sleep(1500);
//        executorService.shutdown();
//        System.out.println(executorService.isShutdown());
        executorService.awaitTermination(3L, TimeUnit.SECONDS);
    }
}
class ShutDownTask implements Runnable{

    @Override
    public void run() {
        try {
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

6.暫停和恢復線程池

//暫停線程池
 pauseAbleThreadPool.pause();
 //恢復線程池
 pauseAbleThreadPool.resume();

代碼實現(xiàn):

//演示每個任務執(zhí)行前后放鉤子函數(shù)
public class PauseAbleThreadPool extends ThreadPoolExecutor {
    private final ReentrantLock lock = new ReentrantLock();
    private Condition unpaused = lock.newCondition();
    private boolean isPaused;

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public PauseAbleThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        lock.lock();
        try {
            while (isPaused) {
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private void pause() {
        lock.lock();
        try {
            isPaused = true;
        } finally {
            lock.unlock();
        }
    }

    public void resume() {
        lock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PauseAbleThreadPool pauseAbleThreadPool = new PauseAbleThreadPool(10, 20, 10l, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("我被執(zhí)行");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10000; i++) {
            pauseAbleThreadPool.execute(runnable);
        }
        Thread.sleep(1500);
        pauseAbleThreadPool.pause();
        System.out.println("線程池被暫停了");
        Thread.sleep(1500);
        pauseAbleThreadPool.resume();
        System.out.println("線程池被恢復了");

    }
}

實現(xiàn)原理及源碼分析:
線程池的組成部分:

  • 線程池管理器
  • 工作線程
  • 任務隊列
  • 任務接口(Task)

在這里插入圖片描述

到此這篇關(guān)于Java線程池由淺入深掌握到精通的文章就介紹到這了,更多相關(guān)Java 線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論