java - 如何修复 'This operation can be a deadlock cause'

标签 java discord deadlock

当我第二次调用 sendDM() 时,我收到死锁警告。我该如何解决这个问题?

我正在使用 JDA Api,并且正在尝试获取我使用 RestAction .complete() 发送的消息

    private void start(){

        sendDM(getP1().getUser());
        sendDM(getP2().getUser());

        EmbedBuilder embedBuilder = new EmbedBuilder();
        textChannel.sendMessage(p1.getUser().getAsMention() + " " + p2.getUser().getAsMention()).queue();
        textChannel.sendMessage(embedBuilder.setTitle("**Match has started - #" + getGameId() + "**")
                        .addField("Info", "ID: " + getGameId() + "\nMap: 7189-0031-5500" + "\nStatus: " + getStatus().toString(),true)
                        .addField("Player 1", p1.getUser().getAsMention() + " - Host", false)
                        .addField("Player 2", p2.getUser().getAsMention(), false)
                        .addField("Lobby", textChannel.getAsMention(), false)
                        .setFooter("Both participants will receive a Private Message where they can submit match results", null).build())
                .queue();


    }

    private void sendDM(User user){

        EmbedBuilder embedBuilder = new EmbedBuilder();
        user.openPrivateChannel().queue((channel) ->
        {
            channel.sendMessage(p1.getUser().getAsMention() + " " + p2.getUser().getAsMention()).queue();
            Message message = channel.sendMessage(embedBuilder.setTitle("**Match has started - #" + getGameId() + "**")
                    .addField("Info", "ID: " + getGameId() + "\nMap: 7189-0031-5500" + "\nStatus: " + getStatus().toString(),true)
                    .addField("Player 1", p1.getUser().getAsMention() + " - Host", false)
                    .addField("Player 2", p2.getUser().getAsMention(), false)
                    .addField("Lobby", textChannel.getAsMention(), false)
                    .addField("**If you win**", ":white_check_mark:", true)
                    .addField("**If you loose**", ":x:", true)
                    .setFooter("Both participants will receive a Private Message where they can submit match results", null).build())
                    .complete();
            message.addReaction("\u274C").complete();
            message.addReaction("\u2705").complete();

        });

    }

我希望它只返回消息,但我收到此错误:

[ForkJoinPool.commonPool-worker-1] ERROR net.dv8tion.jda.api.requests.RestAction - Encountered error while processing success consumer
java.lang.IllegalStateException: Preventing use of complete() in callback threads! This operation can be a deadlock cause
    at net.dv8tion.jda.internal.requests.RestActionImpl.complete(RestActionImpl.java:187)
    at net.dv8tion.jda.api.requests.RestAction.complete(RestAction.java:357)
    at match.Match.lambda$sendDM$0(Match.java:71)
    at net.dv8tion.jda.api.requests.Request.lambda$onSuccess$0(Request.java:83)
    at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

最佳答案

只有一个回调线程用于运行回调。*

您的调用 user.openPrivateChannel().queue((channel) -> {...} 在此单个回调线程中运行。

您的调用 message.addReaction("\u274C").complete(); 会阻塞直到完成,但它将在同一个回调线程上运行,该线程已经忙于运行外部想要运行complete()的回调...你看到了问题。这是在幕后检测到的,并抛出异常以防止发生这种死锁。

只需使用 message.addReaction("\u274C").queue(); 即可。 queue() 立即返回,以便回调线程有机会在外部回调完成后运行它。

请参阅 complete() 的文档和 queue() .

<小时/>

*请参阅这些故障排除文档 here :

Since we decided to use a single-thread pool (1) we only have one thread to execute callbacks. This thread is used by the first callback (2) and cannot be used for the second callback (3).

Due to this reason we simply don't allow using complete() in any callback threads at all. If you use callbacks you should use queue().

(Copyright 2015-2019 Austin Keener, Michael Ritter, Florian Spieß)

关于java - 如何修复 'This operation can be a deadlock cause',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58472506/

相关文章:

java - Jar 可在 Windows 中运行,但不能在 Linux 中运行

java - 如何使用 Mockito 打印与模拟的所有交互

python - 使用带有 discord.py 的 tweepy 将推文发布到特定 channel

java - 什么 java 命令/二进制文件用于打印可读的 java 字节码?

来自 Com 端口的 Java readLine

java - 中心裁剪图像 JavaFX

python - 为多个机器人加载齿轮

c# - 使用 FFMPEG 流式传输 YouTube 音频的示例

java - 为什么静态初始化器中带有 lambda 的并行流会导致死锁?

mysql - 插入导致 InnoDB 中出现死锁。这怎么发生的?