java 限定时间内多次调用目标函数-模拟调度任务

29 篇文章 0 订阅
23 篇文章 0 订阅

java 限定时间内多次调用目标函数-模拟调度任务

最近,spring boot项目中用到了调度任务,执行特定任务代码。使用的xxl-job处理调度。
但是 每次都执行一次目标功能,每次只处理固定数量数据(调用第三方接口限制了数量),造成数据处理过慢,尤其是在需要大量数据需要处理(十万或百万),但是又不是经常有大量数据。就考虑,怎么在一个调度周期内尽可能多的处理数据量,提升数据消化速度。
一开始想到的是,压缩调度周期,由原来的几分钟改为1分钟或更短,但是调度调用日志就很多,且大部分时间都是没有数据处理。
现在考虑增加时间判断代码,并在限定时间尽可能多的执行目标函数。
原来每次只有 一批1000 数据,现在 每次能处理 最少10批次数据

模拟代码如下

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短时间多次调用
 *
 * @author z.y.l
 * @version v1.0
 * @date 2021/11/8
 */
public class MultipleCallsShortTimeTest {
    public static void main(String[] args) {
        try {
            String param = "1-调度传入的内容首位是数字:调度间隔分钟默认1";
            mulCallShortTime1(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void mulCallShortTime1(String param) throws Exception {
        // 可处理的总时间(调度的间隔分钟数) 默认 1分钟,总条数
        int totalMinute = 1,totalSize = 0 ;
        if ( !isEmpty(param) && param.contains(SYMBOL_11)){
            String[] sps = param.split(SYMBOL_11);
            if( isNumeric(sps[0]) ){
                totalMinute = Math.max( 1, Integer.parseInt( sps[0] ) ) ;
            }
        }
        // 总耗时 ms 根据 总可处理毫秒数 计算
        final long totalMs = totalMinute * L_60_1000 ;
        // 函数处理 耗时最大值默认1000ms, 上次 函数结束时间戳, 当前 函数多次执行总耗时 ms
        long max = L_1000, lastTime = System.currentTimeMillis(), total = 0L;
        System.out.printf("开始执行,%d总分钟,%d总毫秒,%d时间戳%n",totalMinute,totalMs,lastTime);
        // 短时间最多次调用目标函数, limit 限制 最大循环数据
        for (int i = 0,limit = totalMinute * INT_60,size ; i < limit ; i++) {
            // 执行函数 获取 判断依据 条数
            size = mulCallFun1();
            // 获取-当前函数执行结束时间戳ms,获取-当前函数耗时ms
            long tempTime = System.currentTimeMillis(), tempMs = tempTime - lastTime;
            // 获取-耗时最大值
            max = Math.max(max,tempMs);
            // 记录耗时
            total += tempMs;
            // 记录总条数
            totalSize += Math.max(0,size);
            System.out.printf("%n%d>>>:%d条数,耗时%dms,最大耗时%dms%n",i,size,tempMs,max);
            // -1 异常,-2 错误,0-1000 没有下批待处理数据, >=1000 当前处理批次数量 最大值 可能还有待处理数据
            if ( size < INT_1000 ){ break; }
            // 计算剩余耗时,比较 最大耗时, 如果 小于 就认为 执行下一次函数 会超时
            if ( totalMs - total <= max ){ break; }
            // 记录时间戳,下一个循环使用
            lastTime = tempTime;
        }
        if( totalSize <= 0 ){
            System.out.println("结束-无数据或执行异常");
        } else {
            System.out.printf("结束-总耗时:%dms,最大耗时%dms,总条数%d",total,max,totalSize);
        }
    }
    /** 目标函数-模拟 */
    private static int mulCallFun1() throws Exception{
        // 使用随机数 生成 不同情况
        int size = nextInt( 0 , INT_30 );
        System.out.print("模拟>>随机数:" + size);

        // 异常的情况
        long sleep = nextLong( L_1000 );
        System.out.print( ",代码处理-睡眠ms:" + sleep );
        TimeUnit.MILLISECONDS.sleep( sleep );
        if ( 0 == size ){ return INT__2; }
        // 错误的情况
        if ( INT_29 == size ){ return INT__1; }

        sleep = nextLong( L_2000 );
        System.out.print( ",接口获取数据-睡眠ms:" + sleep );
        TimeUnit.MILLISECONDS.sleep( sleep );
        // 无数据的情况
        if ( INT_2 >= size ){ return 0; }

        sleep = nextLong( L_1000, L_2000 );
        System.out.print( ",数据处理-睡眠ms:" + sleep );
        TimeUnit.MILLISECONDS.sleep( sleep );
        // 数据不够的情况
        if ( INT_5 >= size ){ return nextInt( 1, INT_1000 ); }
        // 数据充足的情况
        return INT_1000;
    }
    private static final Random RANDOM = new Random();
    private static final int INT_1000 = 1000;
    private static final int INT_29 = 29;
    private static final int INT_30 = 30;
    private static final int INT_60 = 60;
    private static final int INT_5 = 5;
    private static final int INT_2 = 2;
    private static final int INT__2 = -2;
    private static final int INT__1 = -1;
    private static final long L_1000 = 1000L;
    private static final long L_60_1000 = 60000L;
    private static final long L_2000 = 2000L;
    private static final String SYMBOL_11 = "-";
    private static double nextDouble ( double start,double end ){
        return start + ( (end -start) * RANDOM.nextDouble() );
    }
    private static long nextLong ( long start, long end){
        return (long) nextDouble( start, end );
    }
    private static long nextLong ( long end){
        return nextLong( 0L, end );
    }
    private static int nextInt( int start, int end ){
        return start + RANDOM.nextInt( end - start );
    }
    private static int nextInt(){
        return nextInt( 0, Integer.MAX_VALUE );
    }
    private static boolean isNumeric(CharSequence cs){
        if( isEmpty(cs) ){
            return false;
        }
        int len = cs.length();
        for (int i = 0; i < len; i++) {
            if( !Character.isDigit(cs.charAt(i)) ){
                return false;
            }
        }
        return true;
    }
    private static boolean isEmpty(CharSequence cs){
        return null == cs || cs.length() > 0;
    }
}

输出日志

开始执行,1总分钟,60000总毫秒,1636343155141时间戳
模拟>>随机数:16,代码处理-睡眠ms:660,接口获取数据-睡眠ms:1121,数据处理-睡眠ms:1644
0>>>:1000条数,耗时3456ms,最大耗时3456ms
模拟>>随机数:6,代码处理-睡眠ms:420,接口获取数据-睡眠ms:1775,数据处理-睡眠ms:1737
1>>>:1000条数,耗时3933ms,最大耗时3933ms
模拟>>随机数:10,代码处理-睡眠ms:171,接口获取数据-睡眠ms:1854,数据处理-睡眠ms:1095
2>>>:1000条数,耗时3122ms,最大耗时3933ms
模拟>>随机数:25,代码处理-睡眠ms:861,接口获取数据-睡眠ms:76,数据处理-睡眠ms:1019
3>>>:1000条数,耗时1958ms,最大耗时3933ms
模拟>>随机数:27,代码处理-睡眠ms:182,接口获取数据-睡眠ms:1594,数据处理-睡眠ms:1568
4>>>:1000条数,耗时3345ms,最大耗时3933ms
模拟>>随机数:7,代码处理-睡眠ms:97,接口获取数据-睡眠ms:1401,数据处理-睡眠ms:1451
5>>>:1000条数,耗时2950ms,最大耗时3933ms
模拟>>随机数:17,代码处理-睡眠ms:241,接口获取数据-睡眠ms:1359,数据处理-睡眠ms:1837
6>>>:1000条数,耗时3437ms,最大耗时3933ms
模拟>>随机数:17,代码处理-睡眠ms:361,接口获取数据-睡眠ms:1065,数据处理-睡眠ms:1635
7>>>:1000条数,耗时3062ms,最大耗时3933ms
模拟>>随机数:12,代码处理-睡眠ms:767,接口获取数据-睡眠ms:772,数据处理-睡眠ms:1833
8>>>:1000条数,耗时3375ms,最大耗时3933ms
模拟>>随机数:9,代码处理-睡眠ms:787,接口获取数据-睡眠ms:1505,数据处理-睡眠ms:1413
9>>>:1000条数,耗时3706ms,最大耗时3933ms
模拟>>随机数:16,代码处理-睡眠ms:228,接口获取数据-睡眠ms:1636,数据处理-睡眠ms:1284
10>>>:1000条数,耗时3150ms,最大耗时3933ms
模拟>>随机数:27,代码处理-睡眠ms:822,接口获取数据-睡眠ms:1945,数据处理-睡眠ms:1727
11>>>:1000条数,耗时4495ms,最大耗时4495ms
模拟>>随机数:15,代码处理-睡眠ms:622,接口获取数据-睡眠ms:1415,数据处理-睡眠ms:1753
12>>>:1000条数,耗时3791ms,最大耗时4495ms
模拟>>随机数:18,代码处理-睡眠ms:57,接口获取数据-睡眠ms:1865,数据处理-睡眠ms:1774
13>>>:1000条数,耗时3698ms,最大耗时4495ms
模拟>>随机数:21,代码处理-睡眠ms:566,接口获取数据-睡眠ms:1877,数据处理-睡眠ms:1716
14>>>:1000条数,耗时4161ms,最大耗时4495ms
模拟>>随机数:24,代码处理-睡眠ms:266,接口获取数据-睡眠ms:1418,数据处理-睡眠ms:1165
15>>>:1000条数,耗时2852ms,最大耗时4495ms
模拟>>随机数:14,代码处理-睡眠ms:417,接口获取数据-睡眠ms:1522,数据处理-睡眠ms:1440
16>>>:1000条数,耗时3380ms,最大耗时4495ms
结束-总耗时:57871ms,最大耗时4495ms,总条数17000

调度截图

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值