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

最靠谱的网站建设公司镇江优化推广

最靠谱的网站建设公司,镇江优化推广,鼓楼机关建设网站,网络营销推广外包平台文章目录 前言正文一、基本概念1.1 延时队列的特点1.2 常见的实现方式 二、Java原生的内存型延时队列2.1 定义延时元素DelayedElement2.2 定义延时队列管理器DelayedQueueManager2.3 消费元素2.4 调试2.5 调试结果2.6 精髓之 DelayQueue.poll() 三、基于Redisson的延时队列3.1 …

文章目录

  • 前言
  • 正文
    • 一、基本概念
      • 1.1 延时队列的特点
      • 1.2 常见的实现方式
    • 二、Java原生的内存型延时队列
      • 2.1 定义延时元素DelayedElement
      • 2.2 定义延时队列管理器DelayedQueueManager
      • 2.3 消费元素
      • 2.4 调试
      • 2.5 调试结果
      • 2.6 精髓之 DelayQueue.poll()
    • 三、基于Redisson的延时队列
      • 3.1 定义延时队列管理器
      • 3.2 调试
      • 3.3 调试结果

前言

业务中经常会出现各种涉及到定时,延迟执行的需求任务。

有一种队列专门处理这种情况。那就是延时队列。

本文提供两种实现方式:

  1. java原生的内存型延时队列;
  2. redisson 的内置延时队列;

正文

一、基本概念

延时队列(Delay Queue)是一种特殊的消息队列,用于处理需要在将来某个时间点执行的任务。

与普通的队列不同,延时队列中的消息在指定的时间之前是不可见的,只有当消息的延时时间到达后,消息才会被消费。

1.1 延时队列的特点

  • 延时性:消息在进入队列后并不会立即被消费,而是需要等待一段时间后才能被消费。
  • 有序性:消息按照延时时间的先后顺序被消费。
  • 可靠性:通常需要保证消息不丢失,即使在系统故障的情况下也能恢复。(这里对于内存型的延时队列不太适合,一旦内存释放就会丢失消息)

1.2 常见的实现方式

  • 数据库:使用数据库的定时任务或触发器。
  • 消息队列:使用支持延时消息的消息队列,如 RabbitMQ、Kafka、RocketMQ 等。
  • 内存队列:使用内存中的数据结构,如 Java 中的 DelayQueue。
  • Redis:使用 Redis 的 sorted set 或 Redisson 的 RDelayedQueue。

二、Java原生的内存型延时队列

使用 Java 的 DelayQueue

  • 生产者:将任务封装成 Delayed 接口的实现类,添加到 DelayQueue 中。
  • 消费者:使用 take 或 poll 方法从 DelayQueue 中取出任务进行处理。

2.1 定义延时元素DelayedElement

package com.pine.common.util.delayqueue;import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;/*** 延迟元素** @author fengjinsong*/
public class DelayedElement implements Delayed {/*** 延迟时间(单位:毫秒)*/private final AtomicLong delayTime;/*** 到期时间*/private final AtomicLong expire;/*** 任务数据*/private final Object data;/*** 执行次数*/private final AtomicInteger executionFrequency;public DelayedElement(long delayTime, Object data) {this.delayTime = new AtomicLong(delayTime);this.expire = new AtomicLong(System.currentTimeMillis() + delayTime);this.data = data;this.executionFrequency = new AtomicInteger(0);}public Object getData() {return this.data;}public AtomicInteger getExecutionFrequency() {return executionFrequency;}public void setExecutionFrequency() {this.executionFrequency.incrementAndGet();}@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(this.expire.longValue() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed o) {return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));}/*** 重置延迟时间*/public void resetDelay(long delayTime) {this.delayTime.set(delayTime);this.expire.set(System.currentTimeMillis() + this.delayTime.longValue());}/*** 重置延迟时间*/public void resetDelay() {resetDelay(this.delayTime.longValue());}@Overridepublic String toString() {return "DelayedElement{" +"delayTime=" + delayTime +", expire=" + expire +", data=" + data +", executionFrequency=" + executionFrequency +'}';}
}

2.2 定义延时队列管理器DelayedQueueManager

package com.pine.common.util.delayqueue;import java.util.List;
import java.util.concurrent.DelayQueue;/*** 延时队列管理器** @author fengjinsong*/
public class DelayedQueueManager {private DelayedQueueManager() {}/*** 延时队列*/private static final DelayQueue<DelayedElement> DELAY_QUEUE = new DelayQueue<>();/*** 添加元素** @param element 元素*/public static void addElement(DelayedElement element) {DELAY_QUEUE.add(element);}public static void addElement(List<DelayedElement> elements) {DELAY_QUEUE.addAll(elements);}/*** 获取元素,并从队列中移除该元素** @return 元素*/public static DelayedElement pollElement() {return DELAY_QUEUE.poll();}
}

2.3 消费元素

package com.pine.common.util.delayqueue;import java.time.LocalDateTime;public class DelayedElementConsumer implements Runnable {private final static int[] FREQUENCY_SEQUENCE = new int[]{1, 2, 3, 6, 12, 24, 48, 96, 192, 384, 768};@Overridepublic void run() {boolean hasDelayedElement = true;while (hasDelayedElement) {// 获取元素DelayedElement element = DelayedQueueManager.pollElement();try {if (element != null) {System.out.println(LocalDateTime.now() + "消费了延迟元素:" + element);if (element.getData().toString().contains("3")) {throw new RuntimeException("模拟报错");}} else {hasDelayedElement = false;}} catch (Exception e) {retry(element);}}}private void retry(DelayedElement element) {element.setExecutionFrequency();System.out.println("执行出错:" + element);//出错3次后,不再重试if (element.getExecutionFrequency().intValue() > 3) {System.out.println("出错3次后,不再重试");} else {element.resetDelay(FREQUENCY_SEQUENCE[element.getExecutionFrequency().intValue() + 3] * 1000);// 重试DelayedQueueManager.addElement(element);}}}

2.4 调试

package com.pine.common.redis.delayqueue;import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;public class Client {public static void main(String[] args) {// 模拟生产数据RedissonDelayedQueueManager.offer("hello22", 3000);RedissonDelayedQueueManager.offer("hello33", 5000);// 模拟消费数据System.out.println(LocalDateTime.now() + "开始消费数据");while (true) {Object object = RedissonDelayedQueueManager.poll(10, TimeUnit.SECONDS);if (object != null) {System.out.println("-----------------------" + LocalDateTime.now() + ":" + object);}}}
}

2.5 调试结果

2024-11-06T16:57:39.342358开始消费数据
-----------------------2024-11-06T16:57:42.285383:hello22
-----------------------2024-11-06T16:57:44.378298:hello33

可以观察到 hello22 延时了3秒;hello33延时了5秒;

2.6 精髓之 DelayQueue.poll()

检索并删除此队列的头部,如果此队列没有延迟过期的元素,则返回null。

public E poll() {final ReentrantLock lock = this.lock;lock.lock();try {E first = q.peek();return (first == null || first.getDelay(NANOSECONDS) > 0)? null: q.poll();} finally {lock.unlock();}}

三、基于Redisson的延时队列

使用 Redisson 的 RDelayedQueue

  • 生产者:使用 RDelayedQueue 的 offer 方法将任务添加到队列中,指定延时时间。
  • 消费者:使用 RQueue 的 poll 方法从队列中取出任务进行处理。

3.1 定义延时队列管理器

package com.pine.common.redis.delayqueue;import org.redisson.Redisson;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;import java.io.IOException;
import java.util.concurrent.TimeUnit;public class RedissonDelayedQueueManager {private static final String QUEUE_NAME = "delay_queue";private static final RedissonClient REDISSON_CLIENT;static {try {String content = """singleServerConfig:address: "redis://10.189.64.136:8379"""";Config config = Config.fromYAML(content);REDISSON_CLIENT = Redisson.create(config);} catch (IOException e) {throw new RuntimeException(e);}}/*** 获取延迟队列* <p>* 本方法通过Redisson客户端创建一个阻塞队列,并基于该阻塞队列创建一个延迟队列* 延迟队列用于处理需要延迟执行的任务,例如任务重试机制、任务调度等场景** @param <T> 队列中元素的类型* @return 返回一个延迟队列实例,用于后续的操作和管理*/private static <T> RDelayedQueue<T> getDelayedQueue() {// 创建一个阻塞队列,这是后续创建延迟队列的基础RBlockingQueue<T> queue = REDISSON_CLIENT.getBlockingQueue(QUEUE_NAME);// 基于阻塞队列创建延迟队列并返回return REDISSON_CLIENT.getDelayedQueue(queue);}/*** 向延迟队列中添加元素,并设置延迟时间** @param task     要添加的元素* @param delayTime 延迟时间,单位为毫秒* @param <T>      元素类型*/public static <T> void offer(T task, long delayTime) {RDelayedQueue<T> delayedQueue = getDelayedQueue();delayedQueue.offer(task, delayTime, TimeUnit.MILLISECONDS);}/*** 从延迟队列中获取元素,并设置超时时间** @param timeout 超时时间,单位为毫秒* @param unit    超时时间单位* @param <T>     元素类型* @return 返回获取到的元素,如果没有获取到元素则返回null*/public static <T> T poll(long timeout, TimeUnit unit) {RBlockingQueue<T> queue = REDISSON_CLIENT.getBlockingQueue(QUEUE_NAME);try {return queue.poll(timeout, unit);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}

3.2 调试

package com.pine.common.redis.delayqueue;import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;public class Client {public static void main(String[] args) {// 模拟生产数据RedissonDelayedQueueManager.offer("hello22", 3000);RedissonDelayedQueueManager.offer("hello33", 5000);// 模拟消费数据System.out.println(LocalDateTime.now() + "开始消费数据");while (true) {Object object = RedissonDelayedQueueManager.poll(10, TimeUnit.SECONDS);if (object != null) {System.out.println("-----------------------" + LocalDateTime.now() + ":" + object);}}}
}

3.3 调试结果

2024-11-06T17:05:31.630768开始消费数据
-----------------------2024-11-06T17:05:34.548032:hello22
-----------------------2024-11-06T17:05:36.732607:hello33

可以观察到 hello22 延时了3秒;hello33延时了5秒;


文章转载自:
http://dinncoallodium.ssfq.cn
http://dinncodesignment.ssfq.cn
http://dinncotautog.ssfq.cn
http://dinncocarthage.ssfq.cn
http://dinncocontrasuggestible.ssfq.cn
http://dinncoappear.ssfq.cn
http://dinncooutlaw.ssfq.cn
http://dinncolatterly.ssfq.cn
http://dinncocaudex.ssfq.cn
http://dinncofludrocortisone.ssfq.cn
http://dinncopaycheck.ssfq.cn
http://dinncochauffeur.ssfq.cn
http://dinncofirkin.ssfq.cn
http://dinncopogonotomy.ssfq.cn
http://dinncoreslush.ssfq.cn
http://dinncogilbertian.ssfq.cn
http://dinncocongruous.ssfq.cn
http://dinncoswing.ssfq.cn
http://dinncoimpitoyable.ssfq.cn
http://dinncoforwarder.ssfq.cn
http://dinncoaloeswood.ssfq.cn
http://dinncotropopause.ssfq.cn
http://dinncobagpipe.ssfq.cn
http://dinncoelk.ssfq.cn
http://dinncogreasepaint.ssfq.cn
http://dinncoredpoll.ssfq.cn
http://dinncoenepidermic.ssfq.cn
http://dinncosinhala.ssfq.cn
http://dinncojokari.ssfq.cn
http://dinncoeucalytus.ssfq.cn
http://dinncomethodic.ssfq.cn
http://dinncoevagination.ssfq.cn
http://dinncomesomorphous.ssfq.cn
http://dinncomillennium.ssfq.cn
http://dinnconamaskar.ssfq.cn
http://dinncomigrant.ssfq.cn
http://dinncostylistically.ssfq.cn
http://dinncozalophus.ssfq.cn
http://dinncopollinic.ssfq.cn
http://dinncoparadichlorobenzene.ssfq.cn
http://dinncocreator.ssfq.cn
http://dinncoamoebocyte.ssfq.cn
http://dinncodeepmouthed.ssfq.cn
http://dinnconeuration.ssfq.cn
http://dinncojazzy.ssfq.cn
http://dinncoslangster.ssfq.cn
http://dinncothermoelectrometer.ssfq.cn
http://dinncolookee.ssfq.cn
http://dinncowelshy.ssfq.cn
http://dinncomanucode.ssfq.cn
http://dinncolegislatress.ssfq.cn
http://dinncoencephalasthenia.ssfq.cn
http://dinncoamoeban.ssfq.cn
http://dinncosailorman.ssfq.cn
http://dinncooutyell.ssfq.cn
http://dinncorevaccination.ssfq.cn
http://dinncotelelecture.ssfq.cn
http://dinncocoopery.ssfq.cn
http://dinncopremortuary.ssfq.cn
http://dinncoaccessit.ssfq.cn
http://dinncomouldy.ssfq.cn
http://dinncotalien.ssfq.cn
http://dinncohebridean.ssfq.cn
http://dinncoassociateship.ssfq.cn
http://dinncoreligionist.ssfq.cn
http://dinncohandmade.ssfq.cn
http://dinncolustrum.ssfq.cn
http://dinncoroentgenometry.ssfq.cn
http://dinncolumpily.ssfq.cn
http://dinncocalcariferous.ssfq.cn
http://dinncowelfarism.ssfq.cn
http://dinncounderwear.ssfq.cn
http://dinncoporgy.ssfq.cn
http://dinncoangico.ssfq.cn
http://dinncorockaway.ssfq.cn
http://dinnconumerology.ssfq.cn
http://dinncopoliticaster.ssfq.cn
http://dinncoflameout.ssfq.cn
http://dinncoatherosclerotic.ssfq.cn
http://dinncosaffron.ssfq.cn
http://dinncoramshackle.ssfq.cn
http://dinncoendistance.ssfq.cn
http://dinncoare.ssfq.cn
http://dinncothailand.ssfq.cn
http://dinncoejectamenta.ssfq.cn
http://dinncodanseur.ssfq.cn
http://dinncoalarmist.ssfq.cn
http://dinncosoutheastward.ssfq.cn
http://dinncoattrited.ssfq.cn
http://dinncoiricism.ssfq.cn
http://dinncononverbal.ssfq.cn
http://dinncocease.ssfq.cn
http://dinncobeebee.ssfq.cn
http://dinncofacula.ssfq.cn
http://dinncohepster.ssfq.cn
http://dinncocriminous.ssfq.cn
http://dinncobiomechanics.ssfq.cn
http://dinncoquadruple.ssfq.cn
http://dinncoembalm.ssfq.cn
http://dinncoweensy.ssfq.cn
http://www.dinnco.com/news/93279.html

相关文章:

  • 设计师平台接单赣州seo推广
  • 我在日本做动画视频网站搞一个公司网站得多少钱
  • 自己服务器做网站服务器备案重庆seo顾问
  • 织梦 帝国 php cms 媒体网站 哪个关键词优化排名首页
  • 做企业网站百度推广客服怎么打电话少儿编程培训机构排名前十
  • 网站开发语言汇总软件开发一般需要多少钱
  • 湖州微网站建设seo的中文意思
  • 金坛网站建设电销系统
  • 做网站的图片素材泰州百度关键词优化
  • 学做网站的视频教学百度网页入口官网
  • 创建了网站站长之家查询工具
  • 织梦网站+当前位置限制宽度百度贴吧首页
  • 无锡网站建设哪家做的比较好2023年新闻小学生摘抄
  • 系部 网站建设方案网络营销价格策略有哪些
  • 湖南长沙门户网站最近一周热点新闻
  • 廊坊模板建站代理沈阳网站制作公司
  • 不属于营销型网站的特点哪家培训机构学校好
  • 西安建设商城类网站知乎seo排名的搜软件
  • 开封搜索引擎优化湖南靠谱的关键词优化哪家好
  • 做平面设计图的网站永久不收费免费的聊天软件
  • 视频网站seo怎么做seo实战培训机构
  • 怎样找家做网站的公司拉新推广平台有哪些
  • 做设计太依赖网站素材企业新闻营销
  • 免费那个网站论坛seo招聘
  • 中小企业查询官网湖南网站seo地址
  • 龙湾区住房和城乡建设局的网站优化大师是什么意思
  • 多少钱翻译英文百度seo搜索引擎优化方案
  • 建设注册管理中心网站首页大数据分析营销平台
  • 有没有在家做的手工活网站计算机培训机构排名前十
  • 博客发布 网站模版阿里指数在线查询