自定义多阶段倒计时实现分段倒计时

发布于:2024-04-03 ⋅ 阅读:(132) ⋅ 点赞:(0)

直接贴代码好了

情况是这么个情况 老板想要一个倒计时完毕后再接下一个倒计时总共四五个算一轮业务结束的这个样子
然后循环执行这个业务,这些循环执行我就用了xxl-job ,整体业务就用信号量执行了,总的来说是返回给前端的时间是零误差的, 业务处理的都用异步去执行保证时间总的不会误差1秒

@Slf4j
@Component
@RequiredArgsConstructor
public class MultiPhaseTask extends IJobHandler {

    private final int NUMBER_OF_PHASES = 4;
    ExecutorService executor = Executors.newFixedThreadPool(1);
    private final Semaphore semaphore = new Semaphore(1);

    /**
     * 每个阶段持续时间(毫秒)
     */
    int[] phaseDurations = {5000, 35000, 5000, 5000};

    @Override
    @XxlJob(value = "xxxtask")
    public void execute() throws Exception {

        for (int i = 0; i < NUMBER_OF_PHASES; i++) {
            final int phaseIndex = i;
            int phaseDuration = phaseDurations[i];

            executor.submit(() -> {
                try {
                    // 获取信号量,保证按顺序执行
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                // 在阶段开始时调用对应的方法
                methodStart(phaseIndex + 1);
                log.info("轮次: " + (phaseIndex + 1) + " 开始");

                for (int timeLeft = phaseDuration / 1000; timeLeft > 0; timeLeft--) {
                    System.out.println("轮次: " + (phaseIndex + 1) + " - 倒计时 : " + timeLeft + " s");
                    try {
                        // 每秒更新一次倒计时
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }

                methodEnd(phaseIndex + 1);

                System.out.println("轮次: " + (phaseIndex + 1) + " 结束");
                // 释放信号量,允许下一个阶段执行
                semaphore.release();
            });
        }

        executor.shutdown();
        // 等待所有任务完成
        boolean b = executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
        // 重置 executor
        executor = Executors.newFixedThreadPool(1);
    }


    private void methodStart(int phaseIndex) {
        switch (Objects.requireNonNull(GamesRoundStatusEnum.getGamesEnum(phaseIndex))) {
            case WAIT_START:
                startWait();
                break;
            case OPEN_PLAY:
                startOpen();
                break;
            case OPEN_RESULT:
                startResult();
                break;
            case RESULT_DISPLAY:
                startDisplay();
                break;
            default:
                break;
        }
    }

    private void methodEnd(int phaseIndex) {
        switch (Objects.requireNonNull(GamesRoundStatusEnum.getGamesEnum(phaseIndex))) {
            case WAIT_START:
                endWait();
                break;
            case OPEN_PLAY:
                endOpen();
                break;
            case OPEN_RESULT:
                endResult();
                break;
            case RESULT_DISPLAY:
                endDisplay();
                break;
            default:
                break;
        }
    }

本文含有隐藏内容,请 开通VIP 后查看