耗时的同步请求自动转异步请求

耗时的同步请求自动转异步请求

问题描述

现在在项目中碰到一个情况,导出数据到excel,在数据量比较下的时候直接下载,在数据量比较大时保存到服务的文件列表,后续再供用户下载。
也就是需要避免前端因后端处理时间过长而提示超时的问题。

问题处理

步骤:

  1. 主线程开启线程1进行数据读取和转换byte数组,处理结束唤醒主线程
  2. 开启线程2进行计时,到时间后唤醒主线程
  3. 主线程阻塞,等待唤醒
  4. 判断是被哪个线程唤醒的,如果是线程1,直接返回数据,请求结束;如果是线程2,则表示读取转换未完成,需要转换为异步处理,这时直接结束请求,返回提示信息。

计划:

  1. 使用包括主线程在内的3个线程
  2. 使用CountDownLatch进行主线程唤醒

代码实现

伪代码如下:

ThreadPoolTaskExecutor executor;
    
byte[] handle() throws InterruptedException, ExecutionException {
	// 计数器为 1,无论哪个线程计数,都会唤醒主线程
    CountDownLatch latch = new CountDownLatch(1);
    // 记录 是否数据处理完成
    AtomicBoolean flag = new AtomicBoolean(false);

    // 数据读取线程
    Future<List<Map<String, Object>>> future = executor.submit(() -> {
        synchronized (flag){
            flag.set(true);
            latch.countDown();
        }
        return readSomething();
    });
    
    executor.execute(() -> {
        try {
            Thread.sleep(5 * 1000);
        }catch (Exception ignored){}finally {
            latch.countDown();
        }
    });

    if (!flag.get()) {
        latch.await();
    }
    
    if (flag.get()) {
        // 数据读取完成
        List<Map<String, Object>> maps = future.get();
        // 返回下载数据
        return toExcelByte(maps);
    }else {
        // 数据读取未完成,需要转异步,并返回响应
        executor.execute(() -> {
            List<Map<String, Object>> maps;
            try {
                maps = future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
                return;
            }
            toSaveLocal(toExcelByte(maps));
        });
        return "当前数据处理时间较长,请稍后在文件列表中下载".getBytes();
    }
    
}

List<Map<String, Object>> readSomething() {
    return Collections.EMPTY_LIST;
}

byte[] toExcelByte(List<Map<String, Object>> maps) {
    // 数据保存到excel byte
    return new byte[]{};
}

void toSaveLocal(byte[] bytes) {
    // 写到本地服务器,或者文件服务器,以供下载
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值