最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實現手寫一個簡單版的線程池

 更新時間:2021年08月02日 15:43:33   作者:迷路國王  
有些人可能對線程池比較陌生,并且更不熟悉線程池的工作原理。本文就來手寫一個簡單版的線程池,具有一定的參考價值,感興趣的小伙伴們可以參考一下

有些人可能對線程池比較陌生,并且更不熟悉線程池的工作原理。所以他們在使用線程的時候,多數情況下都是new Thread來實現多線程。但是,往往良好的多線程設計大多都是使用線程池來實現的。 為什么要使用線程 降低資源的消耗。降低線程創(chuàng)建和銷毀的資源消耗。提高響應速度:線程的創(chuàng)建時間為T1,執(zhí)行時間T2,銷毀時間T3,免去T1和T3的時間提高線程的可管理性

下圖所示為線程池的實現原理:調用方不斷向線程池中提交任務;線程池中有一組線程,不斷地從隊列中取任務,這是一個典型的生產者-消費者模型。

要實現一個線程池,有幾個問題需要考慮:

  • 隊列設置多長?如果是無界的,調用方不斷往隊列中方任務,可能導致內存耗盡。如果是有界的,當隊列滿了之后,調用方如何處理?
  • 線程池中的線程個數是固定的,還是動態(tài)變化的?
  • 每次提交新任務,是放入隊列?還是開新線程
  • 當沒有任務的時候,線程是睡眠一小段時間?還是進入阻塞?如果進入阻塞,如何喚醒?

針對問題4,有3種做法:

  • 不使用阻塞隊列,只使用一般的線程安全的隊列,也無阻塞/喚醒機制。當隊列為空時,線程池中的線程只能睡眠一會兒,然后醒來去看隊列中有沒有新任務到來,如此不斷輪詢。
  • 不使用阻塞隊列,但在隊列外部,線程池內部實現了阻塞/喚醒機制
  • 使用阻塞隊列

很顯然,做法3最完善,既避免了線程池內部自己實現阻塞/喚醒機制的麻煩,也避免了做法1的睡眠/輪詢帶來的資源消耗和延遲。
現在來帶大家手寫一個簡單的線程池,讓大家更加理解線程池的工作原理

實戰(zhàn):手寫簡易線程池

根據上圖可以知道,實現線程池需要一個阻塞隊列+存放線程的容器

/**
 * Five在努力
 * 自定義線程池
 */
public class ThreadPool {

    /** 默認線程池中的線程的數量 */
    private static final int WORK_NUM = 5;

    /** 默認處理任務的數量 */
    private static final int TASK_NUM = 100;

    /** 存放任務 */
    private final BlockingQueue<Runnable> taskQueue;

    private final Set<WorkThread> workThreads;//保存線程的集合

    private int workNumber;//線程數量

    private int taskNumber;//任務數量

    public ThreadPool(){
        this(WORK_NUM , TASK_NUM);
    }

    public ThreadPool(int workNumber , int taskNumber) {
        if (taskNumber<=0){
            taskNumber = TASK_NUM;
        }
        if (workNumber<=0){
            workNumber = WORK_NUM;
        }
        this.taskQueue = new ArrayBlockingQueue<Runnable>(taskNumber);
        this.workNumber = workNumber;
        this.taskNumber = taskNumber;

        workThreads = new HashSet<>();

        //工作線程準備好了
        //啟動一定數量的線程數,從隊列中獲取任務處理
        for (int i=0;i<workNumber;i++) {
            WorkThread workThread = new WorkThread("thead_"+i);
            workThread.start();
            workThreads.add(workThread);
        }
    }

    /**
     * 線程池執(zhí)行任務的方法,其實就是往BlockingQueue中添加元素
     * @param task
     */
    public void execute(Runnable task) {
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    /**
     * 銷毀線程池
     */
    public void destroy(){
        System.out.println("ready close pool...");
        for (WorkThread workThread : workThreads) {
            workThread.stopWorker();
            workThread = null;//help gc
        }
        workThreads.clear();
    }

    /** 內部類,工作線程的實現 */
    private class WorkThread extends Thread{
        public WorkThread(String name){
            super();
            setName(name);
        }
        @Override
        public void run() {
            while (!interrupted()) {
                try {
                    Runnable runnable = taskQueue.take();//獲取任務
                    if (runnable !=null) {
                        System.out.println(getName()+" ready execute:"+runnable.toString());
                        runnable.run();//執(zhí)行任務
                    }
                    runnable = null;//help gc
                } catch (Exception e) {
                    interrupt();
                    e.printStackTrace();
                }
            }
        }

        public void stopWorker(){
            interrupt();
        }
    }
}

上面代碼定義了默認的線程數量和默認處理任務數量,同時用戶也可以自定義線程數量和處理任務數量。用BlockingQueue阻塞隊列來存放任務。用set來存放工作線程,set的好處就不用多說了。懂的都懂

構造方法中new對象的時候,循環(huán)啟動線程,并把線程放入set中。WorkThread實現Thread,run方法實現也很簡單,因為有一個stop方法,所以這里需要while判斷,之后從taskQueue隊列中,獲取任務。如何獲取不到就阻塞,獲取到的話runnable.run();就執(zhí)行任務,之后把任務變成null

銷毀線程只需要遍歷set,把每個線程停止,并且變?yōu)閚ull就行了

執(zhí)行線程任務execute,只需要從往阻塞隊列中添加任務就行了

測試一下:

public class TestMySelfThreadPool {

    private static final int TASK_NUM = 50;//任務的個數

    public static void main(String[] args) {
        ThreadPool myPool = new ThreadPool(3,50);
        for (int i=0;i<TASK_NUM;i++) {
            myPool.execute(new MyTask("task_"+i));
        }

    }

    static class MyTask implements Runnable{

        private String name;
        public MyTask(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }


        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("task :"+name+" end...");

        }

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "name = "+name;
        }
    }
}

在這里插入圖片描述

結果ok。沒什么問題

到此這篇關于java實現手寫一個簡單版的線程池的文章就介紹到這了,更多相關java 手寫線程池內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java JVM調優(yōu)五大技能詳解

    Java JVM調優(yōu)五大技能詳解

    這篇文章主要為大家介紹了JVM調優(yōu)的五大技能,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • idea創(chuàng)建maven項目速度慢的三種解決方案

    idea創(chuàng)建maven項目速度慢的三種解決方案

    這篇文章主要介紹了idea創(chuàng)建maven項目速度慢的三種解決方案,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 3分鐘純 Java 注解搭個管理系統的示例代碼

    3分鐘純 Java 注解搭個管理系統的示例代碼

    這篇文章主要介紹了3分鐘純 Java 注解搭個管理系統的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • 利用Lambda表達式創(chuàng)建新線程案例

    利用Lambda表達式創(chuàng)建新線程案例

    這篇文章主要介紹了利用Lambda表達式創(chuàng)建新線程案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 深入了解Java排序算法

    深入了解Java排序算法

    本文主要介紹了深入了解Java排序算法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2007-03-03
  • java虛擬機原理:Class字節(jié)碼二進制文件分析

    java虛擬機原理:Class字節(jié)碼二進制文件分析

    class文件全名稱為Java class文件,主要在平臺無關性和網絡移動性方面使Java更適合網絡。它在平臺無關性方面的任務是:為Java程序提供獨立于底層主機平臺的二進制形式的服務。下面我們來詳細解讀下它吧
    2021-09-09
  • java實現文件復制上傳操作

    java實現文件復制上傳操作

    這篇文章主要為大家詳細介紹了java實現文件復制上傳操作,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Java8通過Function獲取字段名的步驟

    Java8通過Function獲取字段名的步驟

    這篇文章主要介紹了Java8通過Function獲取字段名,需要的朋友可以參考下
    2020-04-04
  • SpringAOP中的動態(tài)代理技術深入解析

    SpringAOP中的動態(tài)代理技術深入解析

    這篇文章主要介紹了SpringAOP中的動態(tài)代理技術深入解析,spring默認使用JDK動態(tài)代理實現AOP,類如果實現了接口,spring就會用JDK動態(tài)代理實現AOP,如果目標類沒有實現接口,spring則使用Cglib動態(tài)代理來實現AOP,需要的朋友可以參考下
    2024-01-01
  • java如何連接數據庫executeUpdate()和executeQuery()

    java如何連接數據庫executeUpdate()和executeQuery()

    這篇文章主要介紹了java如何連接數據庫executeUpdate()和executeQuery(),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

双鸭山市| 肇源县| 大连市| 武宣县| 林甸县| 鄂伦春自治旗| 抚顺市| 大田县| 临汾市| 娱乐| 隆林| 宜兰市| 顺义区| 英超| 鄂尔多斯市| 济南市| 平塘县| 双峰县| 石家庄市| 翁牛特旗| 沙河市| 南川市| 吉安县| 青龙| 芦溪县| 英超| 永安市| 上蔡县| 亚东县| 岳西县| 昌邑市| 泽普县| 邢台县| 福建省| 潢川县| 大冶市| 兴海县| 西丰县| 福安市| 涟源市| 云浮市|