当前位置: 首页 > news >正文

Java中手动床架一个线程池

原文:Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列_java等待队列-CSDN博客

package com.thread;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;/*** @program: FlinkTutorial-1.17.0* @description:* @author: gaoyf* @create: 2025-08-03 19:36**/
public class BlockQueue<T> {private static final Logger log = LoggerFactory.getLogger(BlockQueue.class);// 双端队列private Deque<T> deque = new ArrayDeque<>();// 队列的容量private int size;public BlockQueue(int size) {this.size = size;}// ReentrantLock可重入锁来解决这个问题private ReentrantLock lock = new ReentrantLock();// 分别定义两个Condition代表队列满情况的等待室与队列空情况的等待室// 队列空情况的休息室Condition emptyCondition = lock.newCondition();// 队列满情况的休息室Condition fullCondition = lock.newCondition();// 定义阻塞添加任务方法put// 添加任务 阻塞添加public void put(T task) {lock.lock();try {while (size == deque.size()) {try {fullCondition.await();} catch (InterruptedException e) {throw new RuntimeException(e);}}log.debug("task 添加成功 ,{}", task);deque.addLast(task);emptyCondition.signal();} finally {lock.unlock();}}// 这里添加任务会存在两张情况://队列满了:调用fullCondition.await()方法挂起当前生产者线程,也就是让当前生产者线程等待。//队列没满:将任务加入队列中,并调用emptyCondition.signal()通知挂起的消费者。// 编写堵塞拿取任务方法take// 获取任务public T take() {lock.lock();try {while (deque.isEmpty()) {try {emptyCondition.await();} catch (InterruptedException e) {throw new RuntimeException(e);}}T t = deque.removeFirst();fullCondition.signal();log.debug("获取了任务 {}", t);return t;} finally {lock.unlock();}}// 同理,这里拿取任务也会存在两张情况://队列空的:调用emptyCondition.await()方法挂起当前消费者线程,也就是让当前消费者线程等待。//队列存在元素:任务出栈,并返回出栈的任务元素,然后调用fullCondition.signal()通知挂起的生产者。// 以上我们其实我们就完成了一个简单的任务堵塞队列,但是我们会发现,如果这两个方法都是会一直堵塞,显然是不合理的,所以我们这里新增添加和获取任务的超时方法。// 带超时时间的阻塞添加方法offer// 带超时时间阻塞添加public boolean offer(T task, long timeout, TimeUnit timeUnit) {lock.lock();try {long nanos = timeUnit.toNanos(timeout);while (deque.size() == size) {try {if (nanos <= 0) {return false;}log.debug("等待加入任务队列 {} ...", task);nanos = fullCondition.awaitNanos(nanos);} catch (InterruptedException e) {e.printStackTrace();}}log.debug("加入任务队列 {}", task);deque.addLast(task);emptyCondition.signal();return true;} finally {lock.unlock();}}// 我们可以利用fullCondition.awaitNanos来实现超时等待,当超过给定参数时间时,就会被自动唤醒,并且将传入时间-等待时间作为返回值,下一次循环nanos <= 0时,就会判定为本次操作超时失败了// 带超时时间的阻塞获取方法poll// 带超时时间阻塞获取public T poll(long timeout, TimeUnit unit) {// 1.上锁lock.lock();try {long nanos = unit.toNanos(timeout); // 转为毫秒// 2.首先检查队列是否存在元素while (deque.isEmpty()) {try {// 2.1超时判断,返回值是剩余时间if (nanos <= 0) {return null;}// 2.2超时等待log.debug("等待获取任务");nanos = emptyCondition.awaitNanos(nanos);} catch (InterruptedException e) {e.printStackTrace();}}// 3.拿取元素T task = deque.removeFirst();log.info("任务拿取成功:{}", task);// 4.唤醒挂起的生产者fullCondition.signal();return task;} finally {// 释放锁lock.unlock();}}
}

http://www.lryc.cn/news/609154.html

相关文章:

  • [硬件电路-134]:模拟电路 - 运算放大器常见运算:两模拟信号相加、相减、单模拟信号的积分、微分...
  • template<typename R = void> 意义
  • 【Python练习】075. 编写一个函数,实现简单的语音识别功能
  • golang的包和闭包
  • slice() 和 splice()
  • 决策树模型知识点整理:从原理到实战(含可视化与调参)
  • Corrosion2靶机练习笔记
  • 【图像处理基石】如何使用deepseek进行图像质量的分析?
  • 【Django】-9- 单元测试和集成测试(上)
  • Day23--回溯--39. 组合总和,40. 组合总和 II,131. 分割回文串
  • 机器人抓取流程介绍与实现——机器人抓取系统基础系列(七)
  • 深度学习中卷积与互相关
  • [ java Thread 线程 ] 由“一对一“到“一对多“
  • 【Linux网络编程基础--socket地址API】
  • 使用 Vuepress + GitHub Pages 搭建项目文档
  • GraphRAG:基于知识图谱的检索增强生成技术解析
  • 微分方程模型:用“变化率”的语言,描绘世间万物的动态演化
  • async/await和Promise之间的关系是什么?(补充)
  • 图像识别区分指定物品与其他物体
  • SelectDB数据库,新一代实时数据仓库的全面解析与应用
  • Kubernetes滚动更新、蓝绿部署与金丝雀发布方案对比分析及选型建议
  • 延迟任务方案-DelayQueue
  • noob靶机复现笔记
  • 【stm32】GPIO输入
  • 环绕字符串中的唯一子字符串-动态规划
  • 其它IO函数
  • STM32 串口发送
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘scikit-learn’问题
  • Linux环境下使用Docker搭建多服务环境
  • 学习游戏制作记录(实现克隆攻击的克隆复制和水晶代替克隆)8.3