2012-08-30 52 views
4

我把this code如何在Java中永遠運行程序? System.in.read()是唯一的方法嗎?

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()方法中實現這個最好的方法是什麼?

+0

不要停止'httpService'? –

回答

12

離開main方法在Java那樣自動結束該程序。

如果沒有其他非守護程序線程正在運行,則存在JVM。默認情況下,唯一的非守護進程線程是主線程,並且在離開方法main時結束,因此停止JVM。

所以要麼不結束主線程(由不讓main方法返回)創建一個新的非守護線程從不返回(至少直到你的JVM結束)。

由於該規則實際上相當明智有通常完美的候選人這樣的線程。對於HTTP服務器來說,例如,它可能是實際接受連接的線程,並將它們交給其他線程進行進一步處理。只要該代碼正在運行,JVM就會繼續運行,即使方法早已結束運行。

+1

你沒有完全回答這個問題恕我直言。你不是在說如何阻止非守護線程。正如我發佈bellow http://stackoverflow.com/a/33502519/3114959非常優雅的方式來調用'Thread.currentThread()。join();'。 –

+2

在沒有任何實際工作的情況下有目的地阻塞主線程是錯誤的方法。最好將實際工作的線程標記爲非守護線程。如果你沒有這樣的線程,那麼問題是爲什麼你需要一個運行的JVM ;-) –

1

while (true) { ... }應該繼續相當長的時間。當然,你必須找出一些最終阻止它的方法。

一個常見的技巧是有一些volatile boolean running = true,然後主循環爲while (running) { ... }並定義一些線索設置的標準running = false

+3

我想過使用「while(true);」循環,但是運行它的線程會不斷地評估表達式,從而消耗不必要的CPU週期? – ikevin8me

+2

嗯,這取決於它在做什麼。如果它花費大部分時間等待來自HTTP連接的數據,那麼它將不會消耗不必要的CPU週期。我應該澄清,我並不是建議一個空循環(稱爲繁忙的等待),而是一個主事件循環。 – yshavit

5

@ Joachim的回答是正確的。

但是,如果(出於某種原因)你還願意無限期地(無輪詢)塊的主要方法,那麼你可以這樣做:

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()調用不會返回。但是,其他一些線程仍然可以通過中斷線程來解除對線程的阻止。

+2

理論上'wait'可能會虛假地喚醒(沒有相應的notify()調用)。這就是爲什麼你不應該把它叫做循環之外的原因。 –

+0

確實...固定。 –

16

它看起來像一個奇怪的魔法,但以下的伎倆非常優雅的方式

Thread.currentThread().join(); 

因此當前線程,main例如,在join()等待線程main,即本身,以結束。僵持。

當然阻塞的線程不能是守護線程。

1

回到主題,這正是我想要的。順便說一句,這真棒tutorial幫了我很多。

Main.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類延伸的可運行

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 

所以在主方法一個Runnable被實例化和新的Thread如圖
public void start() { 正在使用runnable進行實例化。 這種情況下,JVM將繼續執行該進程,直到您退出該項目或調試器。

順便說一句,就像約阿希姆紹爾張貼在他的回答。