[英]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.