Java - 主方法中的Thread.sleep

Bos*_*one 7 java concurrency thread-safety

我正在审查Java代码,它本质上是一个定期移动/读取/解析某些文件并将数据输出到数据库的重复进程.重复部分(大致)完成如下:

public class CollectorMain {
    public static boolean signalRecieved = false;
    public static void main(String[] args) {
         Runtime.getRuntime().addShutdownHook(new Thread() {
              public void run() {  
              shutdown(); 
         }});
         while(!signalRecieved) {
              Collector.execute();
              try {
                  Thread.sleep(60 * 1000);
              } catch (InterruptedException e) {
                  break;
              }
         }
         // some shutdown logic
    }
    public static void shutdown() {
        signalReceived = true;
    }
}

public class Collector() {
    public static void execute() {
        // Move files from the queue dir to temp location
        // Read, parse files and insert records into database. 
        // Then delete the processed files
    }
}
Run Code Online (Sandbox Code Playgroud)

我的建议是重构代码

  1. 创建Collector实例并将static execute()方法重构为实例方法
  2. 使用Runnable或TimerTask来处理调用

我的论点是,从main方法使用Thread.wait并将其与静态访问相结合并不是处理可重复进程的好方法,尤其是执行文件IO.作者回复(引用)

Runnable的描述说"应该由任何其实例打算由线程执行的类实现".事实上,出于成本效率要求的原因,我故意避免在该程序中使用线程.

这是同一个讨论的另一个引用,希望有助于澄清作者的立场

从技术上讲,Java根本不会被执行,它由JVM解释,然后JVM执行机器指令,以模拟Java代码正在执行.所以它真的是在一个线程或多个线程上执行的JVM.

但作为Java代码编写者,我并不在意.如果我不在Java中创建"线程",那么JVM的工作就好像没有线程一样 - 即使JVM正在使用"隐藏的线程".

Java Pause未执行,它由一系列机器指令模拟,这些指令可能会也可能不会调用操作系统"等待".(它可能会,因为JVM不想旋转,燃烧CPU周期,但这是JVM实现的选择).

所以我有两个问题:

  1. Thread.wait在这种情况下,是否采用合法,安全和可行的方法来执行可重复的任务?如果没有,为什么不,因为只有一个(主要)执行线程?
  2. 在这种情况下使用静态方法(如果有的话)有什么问题?

如果您有任何其他问题,我将很乐意提供其他信息.

Nei*_*fey 6

你真的在争论设计决策而不是绩效决策.

就我所见,你的同事关于如何实现Thread.sleep的声明基本上是不正确的.在合理的操作系统上的合理JVM上,Thread.sleep()是使用O/S本机方法实现的,用于停止线程(或将其置于"定时等待"状态或您想在操作系统上调用它的任何内容) .换句话说,当线程处于休眠状态时,它会占用零CPU.在任何情况下,TimerTask都将使用Thread.sleep(或类似 - 我不只是回忆它是否使用Java 5中引入的park()方法,但它基本上没有区别).

JVM通常不会做出关于线程的秘密决策.如果你要求另一个线程,你会得到一个; 如果你不这样做,你就不会.将为垃圾收集等创建一些"内务"线程,但就您的代码而言,您可以假设没有秘密聪明的线程创建正在进行.

那么,回到你的问题:

  • 睡在主线上本身是完全安全的; 很明显,当主线程处于休眠状态时,它不会执行任何操作,但如果您不需要它,那么这很好;
  • 是否直接在代码中使用Thread.sleep()或使用"计时器"实用程序方法之一再次是一个设计决定,取决于您是否要使用从代码中删除实现细节的通用库,或者您是否愿意将这些细节呈现在您的控制之下; 在性能方面,如果你正确地实施事情,它将几乎没有可能;
  • 无论你有一个静态方法还是有一个收集器实例并不重要 - 它只是一个你需要根据看起来更直观的设计决策:你看到收集器是一个"通用实用程序"类,还是您要求执行操作的状态"事物"?