java - 如何处理 : Call to 'Thread.sleep()' in a loop, 可能正在等待

标签 java thread-safety sleep thread-sleep

伙计们如何处理这样的代码和警告?

private void listenOnLogForResult() {
    String logs = "";
    int timeCounter = 1;
    while (logs.isEmpty()) {
        try {
            timeCounter++;
            Thread.sleep(2000); // Wait 2 seconds
        } catch (InterruptedException e) {
            log.error(e.getLocalizedMessage(), e);
        }
        if (timeCounter < 30) {
            logs = checkLogs()
        } else {
            logs = "Time out";
        }
    }
}
我需要暂停当前线程 2 秒钟以等待文件被填充,但我的 Intelij 在这里出现了问题。
enter image description here
而且我从声纳中收到错误:
SonarLint:要么重新中断此方法,要么重新抛出“InterruptedException”。
我已经尝试过很多 ExecutorService ,但它总是在单独的线程中运行,我需要暂停当前的线程。
请帮忙..

最佳答案

忙等待警告
这是来自 intellij 的一个可疑警告,因为您正在做的事情通常是直接需要的。换句话说,它正在检测一个过度使用的模式,但其使用率不能减少到 0。因此,可能正确的解决方案是告诉 intellij 在这里闭嘴。
它正在查看的问题是 不是 那个Thread.sleep .那不是问题。然而,intellij 对这种模式的检测器需要它来发现这种情况,但这并不是它所提示的,这可能有点难以理解。
IntelliJ 担心的是,您正在浪费周期不断地重新检查 log.isEmpty()没原因。 while 有问题此代码的方面,而不是 sleep .它更愿意看到您调用某种 logs.poll() 的代码。方法将等待直到它被新日志出现的行为主动唤醒。
如果这一切都在单个 java 进程中运行,那么您确实可以重写整个系统(包括重写 log 在这里的任何内容,以及对 checkLogs() 方法的完全重新想象:而不是出去检查,无论 是什么,制作 日志都需要唤醒此代码。
如果不是,您可能需要告诉 intellij 关闭它:如果没有完整的系统重新设计,您正在做的事情是不可避免的。
重新中断警告
这里有一些令人遗憾的异常处理。
一般的异常处理
不写catch记录某些东西并继续移动的块 .这是非常糟糕的错误处理:系统的变量和字段现在处于未知状态(您刚刚捕获并记录了一些东西:当然,这意味着您不知道发生了什么条件导致这条执行线发生!),并且但是代码会一直移动。 “捕获异常并继续运行”风格的代码极有可能导致更多的异常:通常,在未知状态下运行的代码迟早会崩溃和烧毁。
然后,如果以相同的方式处理崩溃和烧毁(捕获它,记录它,继续前进),那么您将获得另一个崩溃和烧毁。你最终得到的代码会在遇到问题时打印 日志中有 186 个异常,除了第一个之外,它们都完全无关 .那是坏 Jade 宇。
您还使调用代码完全无法恢复。异常的要点是它们需要无休止地向上冒泡:要么异常被真正知道如何处理问题的代码捕获(并记录它是 而不是 处理它!),你是使不可能,或者,代码异常应该一直冒泡到入口点处理程序,这是记录错误和中止入口点处理程序的正确位置。
入口点处理程序是通用模块或应用程序运行程序;开箱即用,代码烘焙成 java.exe本身最终会调用您的 psv main()方法是最明显的“入口运行器”,但还有更多:Web 框架最终会调用您的一些代码来处理 Web 请求:您的代码类似于 psv main() :它是入口点,调用它的 web 框架中的代码是入口点运行器。
入口跑者有充分的理由catch (Throwable t) , 并花费他们的 catch 块主要记录它,尽管他们通常应该记录的不仅仅是异常(例如,Web 处理程序应该记录请求详细信息,例如发送了哪些 HTTP 参数以及它是哪个路径请求,也许标题等)。 任何其他代码都不应该这样做,尽管 .
如果您不知道该做什么并且不想考虑该异常可能意味着什么,正确的“无论如何,只需编译 javac”代码策略是将异常类型添加到您的 throws 中。线。如果这不可行,catch 块中的正确代码是:

} catch (ExceptionIDoNotWantToThinkAboutRightNow e) {
    throw new RuntimeException("Uncaught", e);
}
这将确保代码不会只是愉快地继续前进,在未知状态下运行,并将确保您在日志中获得完整的详细信息,并确保调用代码可以捕获并处理它(如果可以),并确保任何自定义日志信息,例如因为 HTTP 请求详细信息有机会进入日志。双赢双赢。
特别是这种情况:InterruptedEx 是什么意思?
当在该 java 进程中运行的某些代码调用 yourThread.interrupt() 时,就是这样InterruptedException可能发生,和 它不可能以任何其他方式发生 .如果用户按下 CTRL+C,或者进入任务管理器并单击“结束进程”,或者如果您的 android 手机决定是时候让您的应用退出,因为其他事情需要内存 - 这些情况中的一部分可能会导致 InterruptedExceptions。您的线程只是在中途被 java 杀死(如果您想对关闭采取行动,请使用 Runtime.getRuntime().addShutdownHook )。唯一的方法是让一些代码调用 .interrupt() ,并且核心库中的任何内容都不会这样做。因此, InterruptedException 意味着您认为“在此线程上调用 .interrupt()”的含义。它是由你决定。
最常见的定义实际上是“我要求你停止”:只是很好地关闭线程。通常,如果您想退出整个 VM,尝试很好地关闭线程是不好的(只需调用 System.shutdown - 您已经需要处理用户按 CTRL+C,为什么要以不同的方式编写两次关闭代码?) - 但是有时您只想停止一个线程。所以,通常最好的代码放在 catch (InterruptedException e)块是 只是 return;没有别的。不要记录任何东西:“中断”是故意的:你写的。很可能在您的代码库中没有任何地方,并且 InterruptedException 没有实际意义:它永远不会发生。
在您的特定代码中,如果您的代码决定停止记录器线程会发生什么,记录器线程会将某些内容记录到错误日志中,然后缩短其 2 秒等待时间以立即检查日志,然后继续运行。这听起来完全没用。
但是,这意味着任何你想要的。如果你想要一个能力,例如用户点击“立即强制检查日志”按钮,然后您可以定义中断日志记录线程只是缩短了 2 秒(但随后只有一个带有注释的空 catch 块,说明这是您设计的方式,显然不要记录它)。如果您还需要一个按钮来“停止日志记录线程”,请使用跟踪“运行”状态的 AtomicBoolean:当点击“停止日志刷新”按钮时,将 AB 设置为“假”,然后中断线程:然后您粘贴的代码需要检查AB和return;关闭线程,如果是 false .

关于java - 如何处理 : Call to 'Thread.sleep()' in a loop, 可能正在等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66764515/

相关文章:

java - 可重入锁 VS 可重入读写锁

javascript 使用 setTimeout() 超时/ sleep

ruby - 在 Ruby 中,如何将 sleep 与 gets 结合起来?我想等待用户响应 1 分钟,否则继续

java - 如何按行值对列进行排序?

java - 如何为动态创建的每个文件创建子文件夹?

Java:从我的sql数据库中获取特定的表

java - 在多线程和高负载场景下使用java file io好吗?

java - 如何检查我的主机是否不允许 SSH 访问

java - 动态线程创建可能出现的问题或安全方法

使用 sleep() 函数循环打印秒数