43.自定義線程池(一)

ThreadPool是線程池,里面是一定數量的線程,是消費者。

BlockingQueue阻塞隊列,線程池中的線程會從阻塞隊列中去拿任務執行。任務多了線程池處理不過來了,就會到Blocking Queue中排隊,等待執行。鏈表結構,特點是先進先出。java中Deque是一個雙向鏈表,操作起來更方便。

main就是生產者,不斷產生新的執行任務。

package com.xkj.thread.pool;import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class BlockingQueue<T> {//1.任務隊列private Deque<T> queue = new ArrayDeque<>();//2.鎖private Lock lock = new ReentrantLock();//3.生產者條件變量private Condition fullWaitSet = lock.newCondition();//4.消費者條件變量private Condition emptyWaitSet = lock.newCondition();//5.容量private int capcity;public BlockingQueue(int capcity) {this.capcity = capcity;}/*** 帶超時的獲取元素* @param timeout* @param unit* @return*/public T poll(long timeout, TimeUnit unit) {lock.lock();try {//將timeout統一轉化成納秒long nanos = unit.toNanos(timeout);while (queue.isEmpty()) { //判斷隊列是否為空try {if(nanos <= 0) {return null;}//阻塞等待,當被喚醒后,隊列不會空,不滿足while條件,程序繼續向下執行//返回的是timeout - 已經等待的時間 = 剩余的時間//防止虛假喚醒nanos = emptyWaitSet.awaitNanos(nanos);} catch (InterruptedException e) {e.printStackTrace();}}//獲取隊列頭部的元素返回,獲取元素后應該從隊列中移除T t = queue.removeFirst();//喚醒生產者,繼續添加元素fullWaitSet.signal();return t;}finally {lock.unlock();}}/*** 獲取元素* @return*/public T take() {lock.lock();try {while (queue.isEmpty()) { //判斷隊列是否為空try {//阻塞等待,當被喚醒后,隊列不會空,不滿足while條件,程序繼續向下執行emptyWaitSet.await();} catch (InterruptedException e) {e.printStackTrace();}}//獲取隊列頭部的元素返回,獲取元素后應該從隊列中移除T t = queue.removeFirst();//喚醒生產者,繼續添加元素fullWaitSet.signal();return t;}finally {lock.unlock();}}/*** 添加元素* @param element*/public void put(T element) {lock.lock();try {while (queue.size() == capcity){try {fullWaitSet.await();} catch (InterruptedException e) {e.printStackTrace();}}queue.addLast(element);//喚醒消費者,繼續獲取任務emptyWaitSet.signal();}finally {lock.unlock();}}/*** 獲取大小* @return*/public int size() {lock.lock();try {return queue.size();}finally {lock.unlock();}}
}
package com.xkj.thread.pool;import lombok.extern.slf4j.Slf4j;import java.util.HashSet;
import java.util.concurrent.TimeUnit;@Slf4j(topic = "c.ThreadPool")
public class ThreadPool {//任務隊列private BlockingQueue<Runnable> taskQueue;//線程集合private HashSet<Worker> workers = new HashSet<>();//核心線程數private int coreSize;//獲取任務的超時時間private long timeout;private TimeUnit timeUnit;public ThreadPool(int coreSize, int queueCapcity,long timeout, TimeUnit timeUnit) {this.coreSize = coreSize;this.timeout = timeout;this.timeUnit = timeUnit;this.taskQueue = new BlockingQueue<>(queueCapcity);}class Worker extends Thread {private Runnable task;public Worker(Runnable task) {this.task = task;}@Overridepublic void run() {// 執行任務// 1.當task不為空執行任務// 2.當task執行完畢,再接著從任務隊列獲取任務并執行while(task != null || (task = taskQueue.take()) != null) {try {log.debug("正在執行...{}", task);task.run();}catch (Exception e) {}finally {task = null;}}synchronized (workers) {log.debug("worker 被移除{}", this);workers.remove(this);}}}//執行任務public void execute(Runnable task) {synchronized (workers) {if(workers.size() < coreSize) {Worker worker = new Worker(task);log.debug("新增worker{},{}", worker, task);// 當任務數沒有超過coreSize時,直接交給worker對象執行workers.add(worker);worker.start();} else {// 當任務數超過coreSize時,加入任務隊列暫存log.debug("加入任務隊列{}", task);taskQueue.put(task);}}}
}
@Slf4j(topic = "c.TestPool")
public class TestPool {public static void main(String[] args) {ThreadPool threadPool = new ThreadPool(2, 10, 1000, TimeUnit.MILLISECONDS);for (int i = 0; i < 5; i++) {int j = i;threadPool.execute(() -> {log.debug("{}", j);});}}
}

?因為調用了BlockingQueue的take方法,當隊列為空的時候,會無限循環等待,所以這兩個線程一直沒有結束。可以調用帶超時的poll方法,超時后,線程就會結束,也從線程集合中移除。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21091.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21091.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21091.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Netfilter/iptables

1. Netfilter組件圖 https://en.wikipedia.org/wiki/Netfilter 其中&#xff1a; etables作用于數據鏈路層&#xff0c;arptables針對ARP, iptables/ip6tables針對IP層。 nftables 是新的包過濾組件. nft是相對應的新的用戶態組件&#xff0c;用于替換etables,arptables,ipt…

從tensorflow導入EarlyStopping能運行但是一直提示未解析

在pycharm中導入早停機的庫時&#xff0c;碰上一個問題 from tensorflow.keras.callbacks import EarlyStopping這一條代碼中&#xff0c;EarlyStopping一直有個紅色波浪線&#xff0c;代表著找不到這個庫&#xff0c;提示未解析啥的。 但是運行是可以運行的&#xff0c;雖然可…

GPT-4o如何重塑AI未來!

如何評價GPT-4o? 簡介&#xff1a;最近&#xff0c;GPT-4o橫空出世。對GPT-4o這一人工智能技術進行評價&#xff0c;包括版本間的對比分析、GPT-4o的技術能力以及個人感受等。 GPT-4o似乎是一個針對GPT-4模型進行優化的版本&#xff0c;它在性能、準確性、資源效率以及安全和…

Anolis OS 8.9安裝Linux 服務器運維管理面板“1Panel”

一、簡介 1.Linux 服務器運維管理面板“1Panel” 使用go語言編寫 2.很多的項目的應用都是采用 docker 技術來實現&#xff0c;這讓 Linux 服務器的運維管理更簡單、更安全。 3.1Panel 采納最新的前端技術&#xff0c;并通過精心設計的UX 交互&#xff0c;為用戶提供更好的用戶…

Linux系統tab鍵無法補齊命令-已解決

在CentOS中&#xff0c;按下tab鍵就可以自動補全&#xff0c;但是在最小化安裝時&#xff0c;沒有安裝自動補全的包&#xff0c;需要安裝一個包才能解決 bash-completion 1.檢查是否安裝tab補齊軟件包&#xff08;如果是最小化安裝&#xff0c;默認沒有&#xff09; rpm -q ba…

關于sprintboot3版本以上中的swagger3.0的使用

文章目錄 1.配置pom.xml(添加以下內容&#xff0c;記住點一下右上方maven下載)2.application.properties添加以下配置信息3.新建swagger的config配置信息&#xff0c;文件位置如下4.添加接口注釋信息訪問swagger文檔 1.配置pom.xml(添加以下內容&#xff0c;記住點一下右上方ma…

抽象一個通用的配置沖突解決方案

最近的開發項目中遇到了一個關于配置沖突的解決和產品設計&#xff0c;一直以來都沒有處理好。最近抽空整理了一下思路和設計&#xff0c;并做了抽象&#xff0c;后續的類似使用&#xff0c;可以做到直接復用。 思路和代碼見&#xff1a;github地址&#xff1a;https://github…

spring:解決findMergedRepeatableAnnotations獲取可重復的元注解(meta-annotation)結果不正確問題

spring-core的注解工具提供的方法 AnnotatedElementUtils.findMergedRepeatableAnnotations用于從AnnotatedElement 對象獲取可重復的注解。但如果注解本身也是可以定義在其他注解之上的元注解(meta-annotation),且該注解也是可重復注解。這個方法就可能會失效。這就是我最近在…

基于java18多端展示+ idea hbuilder+ mysql家政預約上門服務系統,源碼交付,支持二次開發

基于java18多端展示 idea hbuilder mysql家政預約上門服務系統&#xff0c;源碼交付&#xff0c;支持二次開發 家政預約上門系統是一種通過互聯網或移動應用平臺&#xff0c;為用戶提供在線預約、下單、支付和評價家政服務的系統。該系統整合了家政服務資源&#xff0c;使用戶能…

RabbitMQ三、springboot整合rabbitmq(消息可靠性、高級特性)

一、springboot整合RabbitMQ&#xff08;jdk17&#xff09;&#xff08;創建兩個項目&#xff0c;一個生產者項目&#xff0c;一個消費者項目&#xff09; 上面使用原生JAVA操作RabbitMQ較為繁瑣&#xff0c;很多的代碼都是重復書寫的&#xff0c;使用springboot可以簡化代碼的…

Vue3集成Phaser-飛機大戰游戲(設計與源碼)

文章目錄 引言項目初始化游戲設計和結構游戲程序實現Vue頁面嵌入PhaserPreloader 場景加載游戲場景功能實現功能類定義Boom爆炸類Bullet子彈類Enemy敵軍類Player玩家類End游戲結束類 總結 更多相關內容可查看 引言 飛機大戰&#xff08;也被稱為射擊游戲或空戰游戲&#xff09…

輕松上手MYSQL:優化MySQL慢查詢,讓數據庫起飛

?&#x1f308; 個人主頁&#xff1a;danci_ &#x1f525; 系列專欄&#xff1a;《設計模式》《MYSQL應用》 &#x1f4aa;&#x1f3fb; 制定明確可量化的目標&#xff0c;堅持默默的做事。 ?歡迎加入探索MYSQL慢查詢之旅? &#x1f44b; 大家好&#xff01;我是你們的…

如何優雅簡潔的使用YOLOv8

如何優雅簡潔的使用YOLOv8 目錄訓練調用代碼如何一鍵訓練多個yamlexport模型測試多個yaml是否運行正常predict本文提供了 如何優雅簡潔的使用YOLOv8 ???YOLOv8實戰寶典--星級指南:從入門到精通,您不可錯過的技巧 ??-- 聚焦于YOLO的 最新版本, 對頸部網絡改進、添加局…

Crosslink-NX器件應用連載(11): 圖像(數據)遠程傳輸

作者&#xff1a;Hello&#xff0c;Panda 大家下午好&#xff0c;晚上好。這里分享一個Lattice Crosslink-NX器件實現圖像或數據&#xff08;衛星數據、雷達數據、ToF傳感器數據等&#xff09;遠程傳輸的案例&#xff08;因為所描述的內容頗雜&#xff0c;曬圖不好曬&#xff…

react自用小技巧(持續更新中)

react自用小技巧&#xff08;持續更新中&#xff09; 作者&#xff1a;devwolf 導言&#xff1a; 筆者應屆時&#xff0c;投vue2就任一家大食品廠的資訊部后轉成了react&#xff0c;寫了一年出頭的react類組件。然后跳槽到蘇州科技城的一個原做影視渲染的公司開始全面轉hook…

文件批量改后綴名,輕松實現TXT到DOCX格式轉換,高效管理您的文件庫!

文件處理與管理已成為我們日常生活和工作中不可或缺的一環。然而&#xff0c;面對海量的文件&#xff0c;如何高效地進行格式轉換和管理&#xff0c;卻成為了一道難題。今天&#xff0c;我們將為您揭曉一個神奇的解決方案——文件批量改后綴名功能&#xff0c;讓您輕松實現TXT到…

【GPT-4o:開創人工智能新紀元】

GPT-4o&#xff1a;開創人工智能新紀元 最近&#xff0c;GPT-4o問世&#xff0c;再次引發了人們對人工智能技術的關注和討論。這一新型語言模型的出現&#xff0c;不僅在技術上實現了飛躍&#xff0c;也為我們帶來了全新的思考和體驗。接下來&#xff0c;我們將對GPT-4o進行全…

【docker】docker的安裝

如果之前安裝了舊版本的docker我們需要進行卸載&#xff1a; 卸載之前的舊版本 卸載 # 卸載舊版本 sudo apt-get remove docker docker-engine docker.io containerd runc # 卸載歷史版本 apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker…

linux文件共享之samba

1.介紹 Samba是一個開源文件共享服務&#xff0c;可以使linux與windows之間進行文件共享&#xff0c;可以根據不同人員調整共享設置以及權限管理。 2.安裝 一個命令就OK了&#xff1a;yum install -y samba [rootansible01 ~]# yum install -y samba 已加載插件&#xff1a;l…

Python爬蟲之簡單學習BeautifulSoup庫,學習獲取的對象常用方法,實戰豆瓣Top250

BeautifulSoup是一個非常流行的Python庫&#xff0c;廣泛應用于網絡爬蟲開發中&#xff0c;用于解析HTML和XML文檔&#xff0c;以便于從中提取所需數據。它是進行網頁內容抓取和數據挖掘的強大工具。 功能特性 易于使用: 提供簡潔的API&#xff0c;使得即使是對網頁結構不熟悉…