Java 使用计时器删除ListenerAdapter

Java 使用计时器删除ListenerAdapter,java,discord-jda,Java,Discord Jda,所以我有以下问题,我想在文本频道上制作一个小游戏,问题是,我想创建某种超时,这样人们就不会创建多个“listenerAdapter”实例,而这些实例只会使机器人过载。 我用来加载游戏事件的命令(ListenerAdapter如下) @覆盖 公共无效句柄(列表参数、GuildMessageReceivedEvent事件){ //TODO自动生成的方法存根 TextChannel=event.getChannel(); channel.sendMessage(“请键入\“joingame\”加入!”

所以我有以下问题,我想在文本频道上制作一个小游戏,问题是,我想创建某种超时,这样人们就不会创建多个“listenerAdapter”实例,而这些实例只会使机器人过载。 我用来加载游戏事件的命令(ListenerAdapter如下)

@覆盖
公共无效句柄(列表参数、GuildMessageReceivedEvent事件){
//TODO自动生成的方法存根
TextChannel=event.getChannel();
channel.sendMessage(“请键入\“joingame\”加入!”).queue();
event.getJDA().addEventListener(新的MinigameEvent(通道,event.getAuthor(),事件));
}
然后,我用于加载播放器的代码如下:

public class MinigameEvent extends ListenerAdapter {

      private final long channelId, authorId;
      private final int players=3;
      private ArraySet<User> users;
      private String textMsg;
      private Message target;
      private GuildMessageReceivedEvent outTimerEvent;
      private boolean cancelEvent;

      public MinigameEvent(MessageChannel channel, User author, GuildMessageReceivedEvent outTimerEvent) {
          this.channelId = channel.getIdLong();
          this.authorId = author.getIdLong();
          this.outTimerEvent=outTimerEvent;
          cancelEvent=false;
          this.timeOut(channel);
          users=new ArraySet<User>();
          users.add(author);
          textMsg=("registered users: "+author.getName());
          channel.sendMessage(textMsg).queue((new Consumer<Message>()
          {
              @Override
              public void accept(Message t)
              {
                  target = t;    
               }
        }));    
    }

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {

        if(event.getAuthor().isBot()) {
            return;
        }
        //not respond on other channels
        if (event.getChannel().getIdLong() != channelId) {
            return; 
        }
        MessageChannel channel = event.getChannel();
        String content = event.getMessage().getContentRaw();
        if(content.equalsIgnoreCase("joingame")) {

             users.add(event.getAuthor());
             textMsg=textMsg+", "+event.getAuthor().getName();
             target.editMessage(textMsg).queue();
             if(users.size()==players) {
                 event.getChannel().sendMessage("starting").queue();
                 event.getJDA().removeEventListener(this); 
             }
        }

        if(content.equalsIgnoreCase("cancel") && event.getAuthor().getIdLong()==authorId) {
             cancelEvent=true;
             event.getJDA().removeEventListener(this); 
             event.getChannel().sendMessage("this game has been canceled").queue();
        }   
    }

        private void timeOut(MessageChannel channel) {

            Timer timer = new Timer();



            TimerTask cooldown = new TimerTask() {

                @Override
                public void run() {

                    if(cancelEvent) {
                        return;
                    }

                    if(users.size()<players) {

                         outTimerEvent.getJDA().removeEventListener(this); 

                             try {
                                destroyEvent();
                            } catch (Throwable e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                         channel.sendMessage("not enough players, the game has been cancelled").queue();
                    }else {
                        return;
                    }


                }


            };

            timer.schedule(cooldown, 10000L);
        }

        private void destroyEvent() throws Throwable {
            this.finalize();
        }
}
公共类MinigameEvent扩展ListeneraAdapter{
专用最终长通道ID,authorId;
私人决赛整型选手=3名;
私有ArraySet用户;
私有字符串textMsg;
私有消息目标;
私人行会MessageReceivedEvent outTimerEvent;
私有布尔事件;
公共小型游戏事件(MessageChannel、用户作者、GuildMessageReceivedEvent outTimerEvent){
this.channelId=channel.getIdLong();
this.authorId=author.getIdLong();
this.outTimerEvent=outTimerEvent;
cancelEvent=false;
这个。超时(通道);
users=newarrayset();
用户。添加(作者);
textMsg=(“注册用户:+author.getName());
channel.sendMessage(textMsg).queue((新使用者()
{
@凌驾
公共无效接受(消息t)
{
目标=t;
}
}));    
}
@凌驾
MessageReceived上的公共无效(MessageReceivedEvent事件){
if(event.getAuthor().isBot()){
返回;
}
//不在其他渠道回应
if(event.getChannel().getIdLong()!=channelId){
返回;
}
MessageChannel=event.getChannel();
字符串内容=event.getMessage().getContentRaw();
if(content.equalsIgnoreCase(“joingame”)){
添加(event.getAuthor());
textMsg=textMsg+”,“+event.getAuthor().getName();
target.editMessage(textMsg.queue();
if(users.size()==玩家){
event.getChannel().sendMessage(“启动”).queue();
event.getJDA();
}
}
if(content.equalsIgnoreCase(“取消”)和&event.getAuthor().getIdLong()==authorId){
cancelEvent=true;
event.getJDA();
event.getChannel().sendMessage(“此游戏已取消”).queue();
}   
}
专用无效超时(MessageChannel){
定时器=新定时器();
TimerTask冷却时间=新TimerTask(){
@凌驾
公开募捐{
如果(取消事件){
返回;
}

如果(users.size()您的问题是您的
this
引用了最近的类声明。在这种情况下,这是由您的
new TimeTask(){…
创建的匿名类。要引用实际注册为侦听器的外部类,您必须使用
MinigameEvent。此


我强烈建议使用lambda表达式,因为它没有这个问题。另外需要注意的是,使用计时器会导致线程泄漏,因为它们永远不会被代码关闭()。更好的做法是使用一个单独的,您应该重复使用它来安排所需的一切,而不是为每个任务创建一个新的。这可以在流程结束后关闭(如JDA中的onShutdown事件,该事件在调用shutdown()时触发).

为什么不能编写它,这样就可以创建侦听器类的一个单例。因此,第一次实例化它时,它会创建一个静态单例。然后,后续调用将返回同一个实例。@WJS我可能会研究一下,但问题是,它必须适用于不同的服务器,因此可能需要多个实例。我也会重新编译不要为每个游戏创建新的EventListener。
public class MinigameEvent extends ListenerAdapter {

      private final long channelId, authorId;
      private final int players=3;
      private ArraySet<User> users;
      private String textMsg;
      private Message target;
      private GuildMessageReceivedEvent outTimerEvent;
      private boolean cancelEvent;

      public MinigameEvent(MessageChannel channel, User author, GuildMessageReceivedEvent outTimerEvent) {
          this.channelId = channel.getIdLong();
          this.authorId = author.getIdLong();
          this.outTimerEvent=outTimerEvent;
          cancelEvent=false;
          this.timeOut(channel);
          users=new ArraySet<User>();
          users.add(author);
          textMsg=("registered users: "+author.getName());
          channel.sendMessage(textMsg).queue((new Consumer<Message>()
          {
              @Override
              public void accept(Message t)
              {
                  target = t;    
               }
        }));    
    }

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {

        if(event.getAuthor().isBot()) {
            return;
        }
        //not respond on other channels
        if (event.getChannel().getIdLong() != channelId) {
            return; 
        }
        MessageChannel channel = event.getChannel();
        String content = event.getMessage().getContentRaw();
        if(content.equalsIgnoreCase("joingame")) {

             users.add(event.getAuthor());
             textMsg=textMsg+", "+event.getAuthor().getName();
             target.editMessage(textMsg).queue();
             if(users.size()==players) {
                 event.getChannel().sendMessage("starting").queue();
                 event.getJDA().removeEventListener(this); 
             }
        }

        if(content.equalsIgnoreCase("cancel") && event.getAuthor().getIdLong()==authorId) {
             cancelEvent=true;
             event.getJDA().removeEventListener(this); 
             event.getChannel().sendMessage("this game has been canceled").queue();
        }   
    }

        private void timeOut(MessageChannel channel) {

            Timer timer = new Timer();



            TimerTask cooldown = new TimerTask() {

                @Override
                public void run() {

                    if(cancelEvent) {
                        return;
                    }

                    if(users.size()<players) {

                         outTimerEvent.getJDA().removeEventListener(this); 

                             try {
                                destroyEvent();
                            } catch (Throwable e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                         channel.sendMessage("not enough players, the game has been cancelled").queue();
                    }else {
                        return;
                    }


                }


            };

            timer.schedule(cooldown, 10000L);
        }

        private void destroyEvent() throws Throwable {
            this.finalize();
        }
}