轮询功能java实现

java 实现轮询(LongPolling) 轮询java代码实现,观察者模式,门面模式 阅读详情

一、业务背景

由于项目需要满足大量轮询业务需求,需升级原有的轮询功能。改造过程中发现延时队列(DelayQueue)可以满足业务需求,但是论证后发现延时队列的查询、更新和删除时间复杂度为O(N),因此要对延时队列进行优化。

二、延时队列介绍

延时队列使用优先队列(Priority)+延时器(Delay)实现,优先队列可以保证根节点为排序元素的最大值或者最小值,因此轮询实体在重写延时器(Delay)的CompaerTo方法后,可以保证优先队列的根节点始终为最近到期的轮询实体。

三、优化

使用HashMap索引轮询实体,从而使查询和更新的时间复杂度降为O(1),但是删除的时间复杂度并不能优化到O(logn),因为优先队列删除的时间复杂度为O(N)。如果使用红黑树来实现优先队列的功能可以做到删除时间复杂度为O(logN),但是红黑数依然使用时间作为排序规则,所以并不能在这个维度下来做延时队列的删除。因此最终还是选用优先队列来实现轮询功能

四、代码实现

1、延时队列

import com.hey.bean.dto.ModemPollDto;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ModemPollQueue {
  private final transient ReentrantLock lock = new ReentrantLock();
  
  private final Map<String, ModemPollDto> map = new HashMap<>();
  
  private final PriorityQueue<ModemPollDto> q = new PriorityQueue<>();
  
  private Thread leader;
  
  private final Condition available = this.lock.newCondition();
  
  public boolean put(String k, ModemPollDto e) {
    ReentrantLock lock = this.lock;
    lock.lock();
    try {
      this.map.put(k, e);
      this.q.add(e);
      if (this.q.peek() == e) {
        this.leader = null;
        this.available.signal();
      } 
      return true;
    } finally {
      lock.unlock();
    } 
  }
  
  public ModemPollDto take() throws InterruptedException {
    ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
      while (true) {
        ModemPollDto first = this.q.peek();
        if (first == null) {
          this.available.await();
          continue;
        } 
        long delay = first.getDelay(TimeUnit.NANOSECONDS);
        if (delay <= 0L) {
          this.q.poll();
          this.map.remove(first.getModemId());
          return first;
        } 
        first = null;
        if (this.leader != null) {
          this.available.await();
          continue;
        } 
        Thread thisThread = Thread.currentThread();
        this.leader = thisThread;
        try {
          this.available.awaitNanos(delay);
        } finally {
          if (this.leader == thisThread)
            this.leader = null; 
        } 
      } 
    } finally {
      if (this.leader == null && this.q.peek() != null)
        this.available.signal(); 
      lock.unlock();
    } 
  }
  
  public ModemPollDto get(Object o) {
    ReentrantLock lock = this.lock;
    lock.lock();
    try {
      return this.map.get(o);
    } finally {
      lock.unlock();
    } 
  }
  
  public int size() {
    ReentrantLock lock = this.lock;
    lock.lock();
    try {
      return this.map.size();
    } finally {
      lock.unlock();
    } 
  }
  
  public boolean remove(String modemId) {
    ReentrantLock lock = this.lock;
    lock.lock();
    try {
      ModemPollDto remove = this.map.remove(modemId);
      if (remove == null)
        return false; 
      return this.q.remove(remove);
    } finally {
      lock.unlock();
    } 
  }
  
  public ModemPollDto[] toArray() {
    ReentrantLock lock = this.lock;
    lock.lock();
    try {
      return this.q.<ModemPollDto>toArray(new ModemPollDto[this.q.size()]);
    } finally {
      lock.unlock();
    } 
  }
}

2、轮询实体

import java.util.Date;
import java.util.Objects;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ModemPollDto implements Delayed {
  private Integer id;
  
  private String modemName;
  
  private String modemId;
  
  private String modemIp;
  
  private Integer modemType;
  
  private Integer beamNum;
  
  private Integer polingNotWithdraw;
  
  private Integer polingSlot;
  
  private Integer currentPollCnt;
  
  private Integer pollMultiple;
  
  private Long time;
  
  private Long passTime;
  
  private Integer pollCount;
  
  private Integer pollResponseCount;
  
  public boolean equals(Object o) {
    if (this == o)
      return true; 
    if (o == null || getClass() != o.getClass())
      return false; 
    ModemPollDto that = (ModemPollDto)o;
    return Objects.equals(this.modemId, that.modemId);
  }
  
  public long getDelay(TimeUnit unit) {
    return this.time.longValue() - System.currentTimeMillis();
  }
  
  public int compareTo(Delayed o) {
    ModemPollDto item = (ModemPollDto)o;
    long diff = this.time.longValue() - item.time.longValue();
    if (diff < 0L)
      return -1; 
    return 1;
  }
}

3、轮询类

public class RemPollJob {
  @Async
  public void poll() {
    ModemPollQueue queue = PollTaskConstant.remotePoll;
    while (true) {
      try {
        ModemPollDto take = queue.take();
        if (take.getCurrentPollCnt().equals(Integer.valueOf(take.getPolingSlot().intValue() - 1))) {
          addLeaveTheNetCaveat(take, take.getCurrentPollCnt().intValue());
        } else if (take.getCurrentPollCnt().intValue() >= take.getPolingSlot().intValue()) {
          if (take.getPolingNotWithdraw().intValue() == 0) {
            leave(take);
            continue;
          } 
        } 
        take.setCurrentPollCnt(Integer.valueOf(take.getCurrentPollCnt().intValue() + 1));
        take.setPollCount(Integer.valueOf(take.getPollCount().intValue() + 1));
        take.setPassTime(Long.valueOf(System.currentTimeMillis() - take.getTime().longValue()));
        take.setTime(Long.valueOf(System.currentTimeMillis() + (take.getPollMultiple().intValue() * 1000)));
        queue.put(take.getModemId(), take);
        issuePoll(take);
      } catch (Exception e) {
        e.printStackTrace();
      } 
    } 
  }
}
Java 轮询(重发)机制 1.需求: (1):支付成功需要给商户发送异步通知接口 (2):发送失败得情况下需要有重发机制,重发10次,如果10次还是失败,就不重发了 2.思路 : (1):创建表,需要有时间,次数,状态,推送信息,唯一表示 (2):入库 (3):成功更新状态,失败更新状态(唯一标识) 3.技术 (1):TimeUnit是java.uitl.concurrent包下得一个类名,主要功能是暂停线程得操作与Thread.sleep()一样功能都是暂停线程 (2):Thread.s... 阅读详情

相关推荐

JVM常用概念之安全点轮询

在需要进行标记、压缩、清理时,JVM 是如何停止 Java 线程以进行STW的?

nanxiaotao的博客 963

Java:实现负载均衡轮询算法(附完整源码)

Java:实现负载均衡轮询算法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 479

WebSocket 快速入门 - springboo聊天功能

HTTP和WebSocket都是啥?

m0_56308072的博客 1514

Java中的轮询方法总结

本文总结了Java中常见的五种轮询实现方式及其适用场景,希望能够帮助你在实际应用中选择合适的方法来满足业务需求。

程序猿小样的博客 4443

五种Java多线程轮询方式

代码可以直接拿去运行的哦! 测试主程序: /** * 线程轮询的五种方法 * @author chenbin78 * @version 1.0 * @create_date 2021/4/19 10:03 */ public class ThreadPolling { public static void main(String[] args) { //SynchronizedTest synchronizedTest = new SynchronizedTes

木子陈的博客 8366

java 轮询请求_使用RxJava实现网络请求轮询功能

原标题:使用RxJava实现网络请求轮询功能近日有媒体报道称,腾讯重金入股永辉超市旗下生鲜超市超级物种,目前交易已经完成。受此刺激,永辉超市股价迅速涨停,午后临时停牌。若此举成行,超级物种将更有底气对垒阿里巴巴的盒马鲜生,生鲜商超的新零售市场将展开激烈争战。作者简介各位小伙伴们大家早上好,新的一周又开始了,希望大家都能有个好心情迎接新的一周。本篇来自juexingzhe的投稿,分享了一种通过Rx...

weixin_29970399的博客 1261

WEB消息提醒实现之二 实现方式-Jquery Ajax长轮询

Jquery Ajax长轮询原理Jquery Ajax长轮询的原理主要是,前台客户端发送ajax请求到服务器,服务器接收到请求之后会保持住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。 优点:在无消息的情况下不会频繁的请求,耗费资源小。 缺点:服务器保持住连接会消耗资源。jquery ajax长轮询的过程如下图:可以看到,长轮询的关闭连接有两种情况:

艺俊的博客 1万+

java 前端及后台轮询方法总结

java 前端及后台轮询方法总结 前端实现轮询 代码块//定时器开始 $scope.start = function () { timer = function clock() { findFundNetValueByProId(function (result) { $scope.listEntitys=result; $scop

Glen_guilin的专栏 1万+

Java:实现负载均衡加权轮询算法(附带源码)

Java:实现负载均衡加权轮询算法(附带源码)

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 1681

玩转Nginx篇一【轮询策略与权重轮询

Nginx轮询策略配置

qq_42168462的博客 983

面试题---深入源码理解MQ长轮询优化机制

RocketMQ是一款分布式消息中间件,由阿里巴巴开源。它支持高吞吐、低延迟的消息传递,并提供了丰富的消息过滤、顺序消息、事务消息等高级功能。RocketMQ中的消费者拉取消息时,就采用了长轮询机制来优化性能。本文深入探讨了MQ系统中长轮询机制的原理及其在RocketMQ中的实现细节。通过源码分析和Java模拟实现,我们了解了长轮询机制如何优化消费者拉取消息的过程,减少无效请求和资源浪费。

喜欢猪猪 1329

常见面试题----深入源码理解MQ长轮询优化机制

MQ(Message Queue),即消息队列,是一种应用程序对应用程序的通信方法。在分布式系统中,MQ通过消息的写入和检索实现应用程序间的异步通信,解决了应用解耦、异步消息处理、流量削峰等问题。常见的MQ产品包括ActiveMQ、RabbitMQ、Kafka、RocketMQ等。MQ的长轮询机制通过结合Push和Pull模式的优点,实现了消息的实时推送和客户端资源的有效利用。在分布式系统中,长轮询机制广泛应用于实时消息推送、实时通知系统、实时数据监控等场景。

喜欢猪猪 1827

ajax轮询——通过轮询监视某线程是否已结束

html <button onclick="del()">批量删除</button> js <script type="text/javascript"> //批量删除 function del(){ $.ajax({ type: 'POST', url: "http:/...

qq_33391644的博客 359

Android实现无限轮询需求 (附完整源码)

Android实现无限轮询需求 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 247

websocket 实现群聊和私聊的功能

WebSocket介绍 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocketAPI也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握...

bwwd的博客 4384

java权重轮询调度算法实现

权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * 权重轮询调度算法(WeightedRound-RobinScheduling)-Java

君之虞 629

EXT 3.x 使用详解之Ext.Direct(二)---polling,简单实现网页聊天功能

1.先写个JAVA类,如下: Java代码 1. package com.xuyi.web.direct; 2. 3. import java.text.SimpleDateFormat; 4. import java.util.Date; 5. import java.util.Map; 6. import org.ap...

lukezu的博客 208

java-tryLock可轮询可中断可定时的锁

1、从JAVA5.0开始,提供了新的选择:ReentrantLock。 2、可定时和可轮询的锁获取模式由tryLock方法实现。 3、使用tryLock试图获得的锁如果不能同时获得,就回退,并重新尝试。休眠时间由一个特定组件管理。(下面的代码完成转帐) public boolean transferMoney(Account fromAcct,AccounttoAcct,DollarAm...

深未来技术 608
上一篇: springcloud配置https(使用自制证书)
北岸长风
博客等级 码龄10年 2粉丝 4原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值