You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDA Discord开发:触发条件时如何退出方法运行另一方法解决事件阻塞

问题根本原因

JDA 所有的事件回调方法默认都运行在同一个专属的事件调度线程上,你在 onMessageReceived 方法中写了最大耗时8秒的阻塞while循环,直接占住了整个事件线程,后续所有触发的事件(包括表情添加事件)都必须排队等这个循环执行完才能被调度,所以才会出现只有等超时发送times up后才响应表情回答的情况。

修复方案

核心逻辑是把超时检测逻辑从事件线程中剥离,放到独立的调度线程中运行,不阻塞正常的事件分发。

前置准备

首先定义全局调度器和保证线程可见性的状态变量:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

// 全局只需要初始化一个调度器即可
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
// 加volatile关键字保证多线程场景下的状态可见性
private volatile String answered = "notanswered";

修改onMessageReceived方法

移除原来的阻塞循环,替换为延迟调度任务:

public void onMessageReceived(MessageReceivedEvent event) {
    String[] messagelements = event.getMessage().getContentRaw().split("\\s+");
    if (event.getMessage().getContentRaw().equalsIgnoreCase("what is the number beside " + wordanswer) && event.getAuthor().isBot()){
        // 重置答题状态
        answered = "notanswered";
        // 提交8秒延迟的超时检测任务,完全不占用当前事件线程
        scheduler.schedule(() -> {
            if ("notanswered".equalsIgnoreCase(answered)) {
                event.getChannel().sendMessage("times up").queue();
            }
        }, 8, TimeUnit.SECONDS);
    }
}

修改onMessageReactionAdd方法

删除没必要的线程优先级修改逻辑,其余逻辑保持不变即可:

public void onMessageReactionAdd (MessageReactionAddEvent event) {
    if (event.getUser().equals(worker)) {
        if ("notanswered".equalsIgnoreCase(answered)){
            if (event.getReactionEmote().getName().equalsIgnoreCase(emoteanswer)){
                event.getChannel().sendMessage("Correct!").queue();
            } else {
                event.getChannel().sendMessage("Wrong").queue();
            }
            answered = "answered";
        }
    }
}
额外注意事项
  • 如果需要同时支持多频道/多场次的答题,不要用全局的answered变量,改为用ConcurrentHashMap<Long, String>按频道ID、用户ID等维度存储答题状态,避免不同场次的状态互相冲突。
  • 应用停止运行时记得调用scheduler.shutdown()关闭调度器,避免JVM无法正常退出。
  • 不要在任何JDA的事件回调方法中写长时间阻塞的逻辑,所有耗时、延迟类任务都要放到独立线程中执行,这是JDA开发的通用准则。

内容的提问来源于stack exchange,提问作者Isaac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:36:01