8

我拿了这段代码

 28     public static void main(String[] args) throws IOException {
 29         HttpServer httpServer = startServer();
 30         System.out.println(String.format("Jersey app started with WADL available at "
 31                 + "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...",
 32                 BASE_URI, BASE_URI));
 33         System.in.read();
 34         httpServer.stop();
 35     } 

第 33 行“System.in.read()”是否意味着它将阻塞直到有输入?当使用 UNIX rc 脚本启动 Java 应用程序时,这是否也可以工作 - 而不是从命令行手动启动?

我想编写一个 Java 应用程序来监听 HTTP 连接。该应用程序将在系统启动时自动启动(使用 UNIX rc 脚本)。这意味着应用程序将连续运行 - 理论上永远运行,直到故意停止。在 Java main() 方法中实现这一点的最佳方法是什么?

4

7 回答 7

38

它看起来像一个奇怪的黑魔法,但遵循非常优雅的方式

Thread.currentThread().join();

因此,main例如,当前线程等待join()线程main(即其本身)​​结束。陷入僵局。

被阻塞的线程当然不能是守护线程。

于 2015-11-03T15:10:22.063 回答
17

将方法留main在 Java 中不会自动结束程序。

如果没有更多的非守护线程正在运行,则 JVM 存在。默认情况下,唯一的非守护线程是主线程,它在您离开main方法时结束,因此停止 JVM。

因此,要么不结束主线程(不让main方法返回),要么创建一个永远不会返回的新非守护线程(至少在您希望JVM 结束之前)。

由于该规则实际上是非常明智的,因此通常有一个完美的候选者可以使用这样的线程。例如,对于 HTTP 服务器,它可能是实际接受连接并将它们交给其他线程进行进一步处理的线程。只要该代码正在运行,JVM 就会继续运行,即使该main方法早已完成运行。

于 2012-08-30T14:22:07.893 回答
5

@Joachim 的回答是正确的。

但是如果(出于某种原因)你仍然想无限期地阻塞 main 方法(没有轮询),那么你可以这样做:

public static void main(String[] args) {
    // Set up ...
    try {
        Object lock = new Object();
        synchronized (lock) {
            while (true) {
                lock.wait();
            }
        }
    } catch (InterruptedException ex) {
    }
    // Do something after we were interrupted ...
}

由于锁对象只对这个方法可见,所以什么都看不到notify,所以wait()调用不会返回。但是,其他一些线程仍然可以解除阻塞main线程......通过中断它。

于 2012-08-30T14:43:52.733 回答
1

while (true) { ... }应该会持续很长时间。当然,你最终必须想办法阻止它。

一个常见的技巧是有一些volatile boolean running = true,然后有主循环while (running) { ... },并定义线程设置的一些标准running = false

于 2012-08-30T14:22:23.437 回答
1

回到线程,这正是我想要的。顺便说一句,这个很棒的教程对我帮助很大。

主.java

public class Main {
    public static void main(String args[]) {
        ChatServer server = null;
        /*if (args.length != 1)
            System.out.println("Usage: java ChatServer port");
        else*/
            server = new ChatServer(Integer.parseInt("8084"));
    }
}

ChatServer.java 类扩展了一个 Runnable

public class ChatServer implements Runnable
{  private ChatServerThread clients[] = new ChatServerThread[50];
    private ServerSocket server = null;
    private Thread       thread = null;
    private int clientCount = 0;

    public ChatServer(int port)
    {  try
    {  System.out.println("Binding to port " + port + ", please wait  ...");
        server = new ServerSocket(port);
        System.out.println("Server started: " + server);
        start(); }
    catch(IOException ioe)
    {
        System.out.println("Can not bind to port " + port + ": " + ioe.getMessage()); }
    }

    public void start() {  
        if (thread == null) {  
            thread = new Thread(this);
            thread.start();
        }
    }
.... pleas continue with the tutorial

因此,在 main 方法中,正在实例化一个 Runnable,并使用该可运行对象实例化一个新的线程,如图所示
public void start() { 。这种情况下 JVM 会继续执行该过程,直到您退出项目或调试器。

顺便说一句,这与 Joachim Sauer 在他的回答中发布的相同。

于 2016-04-27T08:42:36.297 回答
0

Java 程序在没有非守护线程运行时终止。您所需要的只是拥有一个这样的运行线程。您可以使用无限循环来做到这一点,但这会消耗 CPU 周期。以下似乎是一种合理的方法。

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {}); //submit a task that does what you want (in this case, nothing)
于 2021-12-25T10:51:16.390 回答
-1

我们也可以使用 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();
 }
}
于 2019-08-30T12:31:53.000 回答