`

java如何实现通用的延迟位数?

    博客分类:
  • java
 
阅读更多

电商大家都用过吧,下单后若未支付,通常都有一段支付倒计时,大约15分钟,若时间到了之后,无需支付的,订单将被关闭,库存将被释放。

这种业务就需要需要用到到延迟径向的功能,将任务丢到递减初始值,设置一个延迟时间,变量函数,到了时间之后,将逐步替换为指定的函数消费指定的任务。

下面的代码是一个通用的逐步降低的实现,大家可以直接拿去用。

代码还是比较简单的,技术要点:

 

  • 调用addTask方法将任务丢失到延迟本身中,主要参数(延迟时间,任务信息,替换【任务终止后会进行替换】)
  • 使用到了java中的延迟迭代DelayQueue来放置延迟任务
  • 下面的结构方法会自动调用一个start方法,start方法中会自动启动一个线程,线程从从串行中拉取终止的任务,然后丢到线程池executorService.submit中进行处理,会自动调用创建连续任务中指定的临时函数
  • 主要方法中有使用步骤
    import java.util.concurrent.*;
    import java.util.function.Consumer;
    import java.util.logging.Logger;
    
    public class DelayQueueService<T> {
        Logger logger = Logger.getLogger(DelayQueueService.class.getName());
        //延迟队列名称
        private String delayQueueName;
        private DelayQueue delayQueue = new DelayQueue<>();
        //处理队列中任务的线程池
        private ExecutorService executorService;
    
        public DelayQueueService(String delayQueueName) {
            this(delayQueueName, Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4));
        }
    
        public DelayQueueService(String delayQueueName, ExecutorService executorService) {
            this.delayQueueName = delayQueueName;
            this.executorService = executorService;
            //启动队列消费
            this.start();
        }
    
        /**
         * 添加任务
         *
         * @param delayedTimeUnit 延迟时间单位
         * @param delayedTime     延迟时间
         * @param task            任务
         * @param consumer        任务消费者(到期了会回调)
         */
        public void addTask(TimeUnit delayedTimeUnit, long delayedTime, T task, Consumer consumer) {
            this.delayQueue.offer(new DelayedTask(delayedTimeUnit, delayedTime, task, consumer));
        }
    
        private void start() {
            //轮询从延迟队列中拉取任务,然后调用线程池进行处理
            Thread pollThread = new Thread(() -> {
                while (true) {
                    try {
                        DelayedTask delayedTask = this.delayQueue.poll(100, TimeUnit.MILLISECONDS);
                        if (this.executorService.isShutdown()) {
                            break;
                        }
                        if (delayedTask != null) {
                            executorService.submit(() -> {
                                delayedTask.consumer.accept(delayedTask.task);
                            });
                        }
                    } catch (InterruptedException e) {
                        logger.warning(e.getMessage());
                    }
                }
            });
            pollThread.setDaemon(Thread.currentThread().isDaemon());
            pollThread.setName(this.getClass().getName() + "-pollThread-" + this.delayQueueName);
            pollThread.start();
        }
    
        public void close() {
            if (!this.executorService.isShutdown()) {
                this.executorService.shutdown();
            }
        }
    
        public class DelayedTask implements Delayed {
            //延迟时间单位
            private TimeUnit delayedTimeUnit;
            //延迟时间
            private long delayedTime;
            //到期时间(毫秒)
            private long endTime;
            //延迟任务信息
            private T task;
            //消费者
            private Consumer consumer;
    
            public DelayedTask(TimeUnit delayedTimeUnit, long delayedTime, T task, Consumer consumer) {
                this.delayedTimeUnit = delayedTimeUnit;
                this.delayedTime = delayedTime;
                this.task = task;
                this.endTime = System.currentTimeMillis() + delayedTimeUnit.toMillis(delayedTime);
                this.consumer = consumer;
            }
    
            @Override
            public long getDelay(TimeUnit unit) {
                return unit.convert(this.endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
            }
    
            @Override
            public int compareTo(Delayed o) {
                DelayedTask task = (DelayedTask) o;
                return Long.compare(this.endTime, task.endTime);
            }
        }
    
        public static void main(String[] args) {
            //创建一个延迟队列:用来对超过支付日期的订单进行关闭
            String delayQueueName = "orderCloseDelayQueue";
            //1、创建延迟队列
            DelayQueueService orderCloseDelayQueue = new DelayQueueService(delayQueueName);
            for (int i = 1; i <= 50; i++) {
                //2、调用addTask将延迟任务加入延迟队列
                orderCloseDelayQueue.addTask(TimeUnit.MILLISECONDS, i, "订单" + i, new Consumer() {
                    @Override
                    public void accept(String s) {
                        System.out.println(System.currentTimeMillis() + "," + Thread.currentThread() + ",关闭订单:" + s);
                    }
                });
            }
            //3、系统关闭的时候,调用延迟队列的close方法
            //orderCloseDelayQueue.close();
        }
    }
     
分享到:
评论

相关推荐

    6位数,共有几种排列组合的算法java实现

    6位数,共有几种排列组合的算法,java实现

    Java中限制小数位数问题

    ### Java中限制小数位数问题 在Java编程中,我们经常会遇到需要处理浮点数的情况,特别是当涉及到金融计算、科学计算等对精度有较高要求的领域时,如何有效地控制小数点后保留的位数显得尤为重要。本文将详细介绍在...

    曲线拟合计算(java实现)

    在这个项目中,作者使用Java实现了曲线和直线的拟合功能。 在Java中,曲线拟合通常涉及到数值分析和线性代数的知识。首先,我们需要理解数据点的坐标,这些点可以表示为`(x, y)`对,其中`x`是自变量,`y`是因变量。...

    子网掩码计算java实现方法

    实现通过ip地址和子网掩码位数计算得出子网段的ip地址范围

    java-显示整数个位数

    ### Java 显示整数个位数 #### 知识点概览 1. **Swing 组件使用**:包括 `JFrame`、`JTextField` 和 `JLabel`。 2. **事件监听器**:使用 `ActionListener` 来响应文本框中的输入事件。 3. **数字处理**:提取整数...

    Java实现Shazam声音识别算法的实例代码

    "Java实现Shazam声音识别算法的实例代码" 本文详细介绍了Java实现Shazam声音识别算法的实例代码,包括AudioSystem获取音频、傅里叶变换将时域信号转换为频域信号、获取音频指纹、匹配指纹契合度来识别音频等关键...

    java代码-使用java生成一个固定位数的随机字符串,并加密,和用户密码加密后的密文组合的源代码

    java代码-使用java生成一个固定位数的随机字符串,并加密,和用户密码加密后的密文组合的源代码 ——学习参考资料:仅用于个人学习使用!

    Java实现多个wav文件合成一个的方法示例

    Java实现多个wav文件合成一个的方法示例 本文介绍了Java实现多个wav文件合成一个的方法,涉及java文件流读写、编码转换、解析等相关操作技巧。 知识点1:Java中的文件流读写 在Java中,文件流读写是通过使用`...

    java实现的18位身份证格式验证算法

    以上就是Java实现18位身份证格式验证算法的主要知识点,通过这些步骤,可以有效地检查输入的身份证号码是否符合中国的身份证规则。在开发过程中,应结合实际情况,考虑异常处理和性能优化,以提供更稳定和高效的验证...

    Java语言实现文本转语音

    总的来说,Java实现文本转语音的关键在于利用Jacob库调用操作系统级别的TTS服务。开发过程中,不仅需要理解Java与COM交互的机制,还需要了解Windows TTS引擎的工作原理,以便有效地将文本转化为流畅的语音输出。同时...

    维吉尼亚加密算法的JAVA实现

    在Java中实现维吉尼亚加密算法,我们需要理解以下几个核心概念: 1. **密钥**:维吉尼亚密码的关键在于其密钥,这是一个由字母组成的字符串,决定了加密和解密过程中使用的偏移量。密钥的长度决定了密码表的循环...

    身份证号验证Java实现

    将身份证号码前面的17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。 将这17位数字和系数相乘的结果相加。 用加出来和除以11,取余数。 余数...

    LSB.zip_Java实现lsb_LSB的java_LSB算法JAVA实现_java实现LSB算法_java实现信息LSB

    以下是对该算法及其Java实现的详细解释。 **LSB算法原理** LSB算法基于数字二进制表示,其核心思想是利用图像每个像素点颜色值的最低位进行信息隐藏。通常,图像由红、绿、蓝(RGB)三个通道组成,每个通道的每个...

    Java实现凯撒加密

    **Java实现凯撒加密** 凯撒加密是一种古老且简单的替换式密码加密技术,它通过将明文中的每个字符向右(或向左)平移固定数量的位置来实现加密。这种加密方式最早由古罗马的凯撒大帝使用,用于军事通信。在Java中...

    java使用google身份验证器实现动态口令验证的示例

    "java 使用 Google 身份验证器实现动态口令验证的示例" 本篇文章主要介绍了使用 Java 语言实现 Google 身份验证器来实现动态口令验证的示例代码。Google 身份验证器是一种基于时间的单次密码(TOTP)算法,能够生成...

    排序算法9种--java实现

    这里我们专注于九种不同的排序算法的Java实现,这些算法在SortJavaVersion.zip压缩包中进行了整理,供学习和参考。 1. 冒泡排序(Bubble Sort):冒泡排序是一种简单的排序算法,它重复地遍历待排序的数列,一次...

    java实现的布隆过滤器算法

    在提供的压缩包文件`Bloom Filter`中,可能包含了具体的Java实现代码,你可以通过阅读和分析这些代码来深入理解布隆过滤器的工作原理和Java实现细节。此外,还可以通过测试不同参数组合下的性能,进一步了解布隆过滤...

    Java实现GeoHash算法

    Java实现GeoHash算法是一种在IT领域中用于地理位置数据存储和检索的技术。GeoHash将经纬度坐标转换为字符串,使得地理位置可以被高效地索引和查询。这种算法利用了空间分割和编码策略,使得相邻的位置在编码后具有...

    s-des算法的Java实现和C++实现

    S-DES的Java实现会涉及对位数组的操作,如`BitSet`的`flip`, `set`, `get`等方法,以及`toString()`方法将位数组转换为字节表示。 **C++实现**: C++提供了丰富的位操作符,如`&`, `|`, `^`, `, `&gt;&gt;`,这使得实现S-...

    Java实现GPS全球定位系统定位数据的提取

    ### Java实现GPS全球定位系统定位数据的提取 #### 引言 全球定位系统(Global Positioning System,简称GPS)是一种重要的导航技术,广泛应用于车辆跟踪、个人定位、地图绘制等领域。GPS系统主要由三大部分组成:...

Global site tag (gtag.js) - Google Analytics