簡體   English   中英

如何在后台線程中啟動服務器並知道服務器在啟動時未引發異常?

[英]How can I start a server in a background thread and know that the server did not throw exception on startup?

我有一個封裝服務器套接字即服務器功能的類。
該類的接口是:

class Server{  
  public void start();  
  public void stop();  
}

開始如下:

public void start(){  
   ExecutorService tp = Executors.newSingleThreadExecutor();  
   while(!stop){  
    try {  
        Socket clientConnection = serverSocket.accept();  
        tp.execute(new ClientProcessor(clientConnection));                
    } catch (IOException e) {  
            stop = true;
    }  
   }    

我很難弄清楚如何在不增加main成本的情況下開始這一工作。
我的意思是我需要從后台線程啟動服務器,所以我想到了以下幾點:

ExecutorService tp2 = Executors.newSingleThreadExecutor();  
 tp.submit(new Runnable(){  
     public void run(){  
    Server s = new Server();
        s.start();  
     }  
 });  
}

但是我要知道的是服務器已啟動並且未引發異常。 我怎樣才能做到這一點?
即我如何從main線程知道后台服務器已正常啟動,因此我可以繼續執行其余操作?

啟動服務器。 稍等一會。 嘗試連接到本地堆棧上。 如果連接成功,您將獲得勝利-只需關閉臨時連接即可。

一種簡單的方法是收集集合中的所有異常,並在某個時間點將它們返回到前台線程。

class Server{  
    private Collection<? extends Exception> exceptions = new ArrayList<Exception>();

    public void start()
    {
      try{ /* do something*/ }
      catch(Exception e)
      {
          exceptions.add(e)
      }
    }

    public void stop();

    public Collection<Exception> getAllExceptions()
    {
        return exceptions;
    }

    public boolean checkOk()
    {
        return 0 == exceptions.size();
    }    

}

詳細說明如何在線程之間傳輸數據:

如果您聲明服務器的方式與我上面的建議類似,那么我們可以更改用於生成服務器的代碼以傳輸serverStartupOk信息:

ExecutorService tp2 = Executors.newSingleThreadExecutor();  
final boolean[] result = new boolean[1]; //Final object so it can pass between threads
 tp.submit(new Runnable(){  
     public void run(){  
    Server s = new Server();
        s.start();  
        result[0] = s.checkOk(); // Retrieve the check from the server, store it in 
                                 // final array variable
     }  
 });

boolean serverStartupOk = result[0];
System.out.println("Server startup succesful: " + Boolean(serverStartupOk).toString());
}

這是一個非常簡單的示例(盡管有許多更好的方法,也有更復雜的方法):

interface Server implements Thread{
    public void startup();
    public void shutdown();
}

class MyServer implements Server{
    private Exception serverError=null;
    ExecutorService singleThreadManager;

    public Exception getServerError(){
        return serverError;
    }

    public void run(){    
       while(!stop){  
            try {  
                 Socket clientConnection = serverSocket.accept();  
                 singleThreadManager.execute(new ClientProcessor(clientConnection));               
            } catch (IOException e) { 
                 serverError = e;
                 // stop = true;
                 shutdown(); // shutdown cleanly after exception
            }
       } 
    } 

    public void startup(){
       singleThreadManager = Executors.newSingleThreadExecutor();
        // do setup tasks and then
        start(); // thread.run() will now be called asynchronously
    }
}

public static void main (String ... args){
    MyServer s = new MyServer();
    s.startup();
    // whenever you want you can now call
    Exception x = s.getServerError();
    // to see whether the server has shutdown because of an error.
}

也許您可以在主應用程序中實現事件處理程序。 您的主應用程序應注冊為服務器類的事件偵聽器。

請看下面的鏈接,它為您提供了C#事件處理的示例和Java的相同示例。

http://scatteredcode.wordpress.com/2011/11/24/from-c-to-java-events/

使用您自己的ThreadPoolExecutor而不是Executors中的預先烘焙的ThreadPoolExecutor 然后覆蓋TPE提供的afterExecute掛鈎,以執行您想對異常執行的任何操作。

我在這里在兩行之間讀了一點,但看來您想知道套接字上的初始偵聽是否成功。 如果您要等待,看看是否有任何客戶端發生故障,則無需在其他線程中運行它。

如果這是正確的,那么您可以在啟動線程處理客戶端連接之前捕獲初始TCP服務器套接字實例發出的任何異常。 將服務器傳遞到新線程,而不是在新線程中創建服務器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM