保持主方法运行的最佳方式

5
我使用了一种方法来保持主方法运行。
public static void main(String[] args) throws InterruptedException {
    while (true) {
        TimeUnit.SECONDS.sleep(1);
    }
}

但是我不确定这是否是最好的方式。

有人能给我一些建议吗?


我有一些需要主方法加载的服务。 - dai
1
这绝对是最简单的方式,但如果你正在编写新软件,请改用事件驱动架构,这样总有调度程序/计时器/监听器在等待并保持事物运行。 - LenglBoy
这个被称为“自旋等待”,是一种反模式(高CPU)。例如,您可以使用阻塞调用ReadLine,只需按Enter键即可结束程序。另一种方法是在某些类型的WaitHandle上进行阻塞,该WaitHandle由其他线程发出信号(例如通过网络IO实现远程关闭)。 - Fildor
2
@JonSkeet 这是1秒钟,而不是1毫秒。 - shmosel
3
当Jon Skeet让一个线程休眠时,该线程会一直休眠,直到Jon Skeet准备好让它唤醒。 - Dawood ibn Kareem
显示剩余10条评论
4个回答

2

最好的方法是保持主线程不进入终止/死亡状态。 以下是我经常使用的两种方法-

 public static void main(String[] args) throws InterruptedException {

    System.out.println("Stop me if you can");
   Thread.currentThread().join(); // keep the main running
  }

另一种方法是创建ReentrantLock并在其上调用wait():
public class Test{
private static Lock mainThreadLock = new ReentrantLock();

public static void main(String[] args) throws InterruptedException {

    System.out.println("Stop me if you can");
    synchronized (mainThreadLock) {
        mainThreadLock.wait();
     }
}

-2
你应该使用 ExecutorService 并提交一个等待读取你服务的输出的任务。
package demo;

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class TaskDemo {
    public static void main(String[] args ) {
        System.out.println("Hello");

        ExecutorService threadPool = Executors.newFixedThreadPool(1);

        Runnable task = () -> {
            try {
                //Loop to read your services's output
                Thread.sleep(1000);
                System.out.println("This is from Task");
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        };
        threadPool.execute(task);
        //Wait for the task to finish and shutdow the pool
        threadPool.shutdown();
    }
}

@Frank.Dai:这样,主方法将一直运行,直到任务完成,因此只需让任务保持运行,直到您想要停止为止。 - nautilusvn
你需要通过这种方式创建一个新的线程,但我认为这不是最佳的方法。 - dai
@Frank.Dai:我认为如果我们想要等待某些东西,最好的方法是使用线程,因为它不会阻塞我们的主线程去执行其他任务。当等待线程完成其任务后,它会向主线程发送一个信号。 - nautilusvn

-2

您有许多选择,其中一些包括:

  • 简单线程
  • TimerTask
  • ScheduledExecutorService

简单线程:

public class Task {
  public static void main(String[] args) {
      final long timeInterval = 1000;
      Runnable runnable = new Runnable() {
       public void run() {
          while (true) {
              System.out.println("Running Task ...");
                try {
                   Thread.sleep(timeInterval);
                } catch (InterruptedException e) {
                   e.printStackTrace();
                }
          }
       }
      };
      Thread thread = new Thread(runnable);
      thread.start();
  }
 }

计时器任务:

 import java.util.Timer;
 import java.util.TimerTask;
 public class Task {
     public static void main(String[] args) {
          TimerTask task = new TimerTask() {
               @Override
               public void run() {
                   System.out.println("Running Task ...");
               }
          };
          Timer timer = new Timer();
          long delay = 0;
          long intevalPeriod = 1000; 
          timer.scheduleAtFixedRate(task, delay,intevalPeriod);
      } 
 }

ScheduledExecutorService:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Task {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
             public void run() {
               System.out.println("Running Task ...");
             }
        };
    ScheduledExecutorService service = Executors
                .newSingleThreadScheduledExecutor();
    service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);
    }
 }

-3

以下是一种保持Java实例运行直到您想要退出的方法。使用GUI来完成:

public static void main(String[] args){
    JFrame jFrame = new JFrame();
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.setLocationRelativeTo(null);
    jFrame.setSize(480, 260);
    jFrame.setVisible(true);
    //do some task here
}

2
当然,只是说一下。这种解决方案的副作用是一个GUI界面,不确定是否需要。但是由于不知道是否不需要,我没有投反对票。 - Fildor
2
为什么要引入一个新的Swing依赖?!如果你不确定他是否有GUI,甚至不应该建议这个解决方案。 - Honza Zidek
@HonzaZidek 只是让他知道的一种方式,我并没有说这是最好的解决方案。 - Jswq
1
因为最后一段被踩了:守护线程恰恰相反:它是一个不会阻止JVM关闭的线程。如果正在运行主线程的线程是唯一的非守护线程,那么JVM将关闭。 - Jon Skeet
1
@Jaycee 如果他没有GUI,那么这不仅仅是“不是最好的解决方案”,而是完全错误的解决方案。在没有思考的情况下引入奇怪的冗余依赖关系总是错误的解决方案。 - Honza Zidek
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接