【问题标题】:Is my while loop looping too fast for my method?我的 while 循环对我的方法来说循环太快了吗?
【发布时间】:2016-04-30 05:53:47
【问题描述】:

我有一个方法chatHandler();,其中包含相当多的代码。它还与程序的其余部分一样在单独的线程上运行。

main 方法中,我有一个while 循环,只要running == true 像这样运行它:

while (running) {
  chatHandler();
}

(问题 1)我的问题是,由于我在不同的线程上运行 chatHandler();... 调用该方法的速度是否可以比其中的代码运行得更快?我的程序的结果似乎告诉我情况就是这样。

这对 Google 来说似乎也太具体了,就在你烤我之前。因此,如果问题 1 是肯定的,那么我如何确保 while 函数的循环速度与 chatHandler(); 可以处理的一样快?

这是我的chatHandler(); 方法中的代码:

public static void chatHandler() {
  new Thread(new Runnable() {
    public void run() {

      LocalDateTime now = LocalDateTime.now();
      int hour = now.get(ChronoField.HOUR_OF_DAY);
      int minute = now.get(ChronoField.MINUTE_OF_HOUR);
      int second = now.get(ChronoField.SECOND_OF_MINUTE);

      String hourSyntax = Integer.toString(hour);
      String minuteSyntax = Integer.toString(minute);
      String secondSyntax = Integer.toString(second);

      if (hour < 10) {
        hourSyntax = "0" + hourSyntax;
      }

      if (minute < 10) {
        minuteSyntax = "0" + minuteSyntax;
      }

      if (second < 10) {
        secondSyntax = "0" + secondSyntax;
      }

      String chatChecker = "[" + hourSyntax + ":" + minuteSyntax + ":" + secondSyntax +
        "] [Server thread/INFO]: <";
      //System.out.println(chatChecker);
      outputPretext = outputLine.substring(0, 34);

      if (outputPretext.equals(chatChecker)) {
        userNameArray = outputLine.split("~");
        preUserName = userNameArray[1];
        userNameArray2 = preUserName.split(">");
        userName = userNameArray2[0];
        teamCheck = outputLine.substring(34, 36);
        playerMessageArray = outputLine.split(">");
        playerMessage = playerMessageArray[1].substring(1);

        /**
        twitchRank = "§T§r§~";
        youTubeRank = "§Y§r§~";
        owner = "§O§r§~";
        admin = "§A§r§~";
        spookRating1 = "§1§r§~";
        spookRating2 = "§2§r§~";
        member = "§M§r§~";
        */

        //chatCurseReplace();
        //chatSpamCheck();
        //mutedPlayer();

        switch (teamCheck) {

          case "�T":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"Twitch \",\"bold\":true,\"color\":\"dark_purple\"},{\"text\":\"" + userName + "\",\"color\":\"blue\"},{\"text\":\" » " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�Y":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* You\"},{\"text\":\"Tube \",\"bold\":true,\"color\":\"red\"},{\"text\":\"" + userName + "\",\"bold\":true,\"color\":\"blue\"},{\"text\":\" \",\"bold\":true},{\"text\":\" » " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�O":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"Owner \",\"bold\":true,\"color\":\"dark_red\"},{\"text\":\"" + userName + "\",\"color\":\"red\"},{\"text\":\" > " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�A":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"Admin \",\"bold\":true,\"color\":\"dark_red\"},{\"text\":\"" + userName + "\",\"color\":\"red\"},{\"text\":\" » " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�1":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"[\",\"color\":\"dark_green\"},{\"text\":\"S\",\"color\":\"green\"},{\"text\":\"]\",\"color\":\"dark_green\"},{\"text\":\" \"},{\"text\":\"" + userName + "\",\"color\":\"blue\"},{\"text\":\" » " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�2":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"[\",\"color\":\"dark_green\"},{\"text\":\"Spook\",\"color\":\"green\"},{\"text\":\"]\",\"color\":\"dark_green\"},{\"text\":\" \"},{\"text\":\"" + userName + "\",\"color\":\"blue\"},{\"text\":\" » " + playerMessage + "\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "�M":
            try {
              writer.append("/tellraw @a [\"\",{\"text\":\"* \"},{\"text\":\"" + userName + "\",\"color\":\"dark_gray\"},{\"text\":\"  » \"},{\"text\":\"" + playerMessage + "\",\"color\":\"gray\"}]");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;

          case "NO":
            break;

          default:
            try {
              writer.append("say Chat Error: no team");
              writer.newLine();
              writer.flush();
            } catch (IOException e) {
              e.printStackTrace();
            }
            break;
        }
        outputLine = "****************************************************************";
      }
    }
  }).start();
}

就是这样,谢谢!

【问题讨论】:

  • 我需要更多上下文来更好地解释;但是,根据您的代码,更好的方法是始终在后台运行一个线程(处理聊天消息),而不是每次都启动一个新线程......(看起来你正在做,再次断章取义。)
  • 你为什么首先使用线程? (是的,除非您添加特定的同步原语,否则无法保证您的代码运行的顺序。)
  • 看起来您将启动数千个线程。每次调用chatHandler() 都会启动一个新线程并立即返回。你应该很快地填满内存,更不用说让线程调度器在同时运行这么多线程时头疼。
  • @Kaelinator 似乎您想确保仅在上一次调用完成后才调用 chatHandler 方法。如果是这样,您可以在与while 循环相同的线程中完成这项工作,而不是产生一个新线程。

标签: java multithreading loops methods while-loop


【解决方案1】:

问题 1 的答案:是的!哦是的!确实!绝对!

chatHandler() 创建一个新线程并启动它,然后立即返回。

那个时候线程几乎没有开始运行。

然后你的循环转过来再次调用它!

第一个线程甚至达到进入run()方法的地步时,你的循环可能已经启动了几十个线程。

如果您的代码遇到线程饥饿,我不会感到惊讶。


所以,问问自己这个问题:为什么您尝试在不同的线程中运行代码?

如果您只想以代码可以处理的速度运行循环,只需直接运行代码即可。

【讨论】:

  • 我为该方法创建了一个新线程,因为我已经运行了其他方法,例如 thread.sleep 等。有没有其他方法可以尽可能快地循环(无需直接编码)?喜欢在方法的末尾设置一个布尔值吗?
  • 解决了,我现在有了它,它可以调用 chatHandler(); 并在该线程中运行 while 循环。谢谢!
【解决方案2】:

您没有在不同的线程上运行 chathandler()。您在不同线程上运行的是匿名 Runnable 子类的 run() 方法。 chathandler() 方法本身正在您的主线程中运行。

每次调用 chathandler() 时,它都会创建一个匿名 Runnable 子类的新实例并启动它,然后返回。无论 Runnable 的 run() 方法运行多快,这种情况发生的速度与主线程循环的速度一样快。这会产生大量的 Runnable 副本,每个副本都在自己的线程中运行其 run() 方法。

根据您的预期,您似乎不需要多个线程。只需直接从主线程调用 Runnable 的 run() 方法,而不是通过 chathandler() 方法间接调用它。

【讨论】:

    【解决方案3】:

    除非您自己编写并发代码,否则无法保证并发代码的运行顺序。在这种情况下,您很可能会产生数千个线程,但这取决于时间。

    在我看来,在这种情况下,您正在滥用并发编程工具。

    并发代码的存在只是因为在一些相对罕见的情况下它可以提高性能。 这是一个黑客。

    所以回答问题 1:是的

    回答问题 2:您可以等待线程运行完成,或者,您可以简单地停止使用线程。只需调用该函数,而不是尝试使用您不需要的功能。这是因为线程的目标是一次做不止一件事,但是等待每个线程运行完成后再生成一个新线程会破坏整个要点。

    【讨论】:

    • 我不会说多线程很少见或被破解。这是非常常见且绝对需要的。
    • @Andreas 多线程不是解决大多数问题的好选择,当然,这取决于您的工作内容。在 90% 的情况下(如 OP),最好顺序运行代码。我将并发称为 hack,因为它的存在只是为了提高程序的性能。它增加复杂性只是为了(有时令人难以置信的)性能优势,但不应出于任何其他原因使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多