0

我有一个封装了服务器套接字的类,即服务器功能。
该类的接口是:

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线程中知道后台服务器启动正常,所以我可以继续进行其余操作?

4

6 回答 6

1

启动服务器。稍等一会。尝试在本地堆栈上连接到它。如果连接成功,您就有了赢家 - 只需关闭临时连接。

于 2013-03-01T15:24:33.813 回答
0

一个简单的方法是收集一个集合中的所有异常,并在某个时间点将它们返回到前台线程。

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());
}
于 2013-03-01T14:09:24.997 回答
0

这是一个非常简单的示例(尽管有许多更好且更复杂的方法):

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.
}
于 2013-03-01T14:14:06.750 回答
0

也许你可以在你的主应用程序中实现一个事件处理程序。您的主应用程序应注册为服务器类的事件监听器。

请查看以下链接,它向您展示了 C# 的事件处理示例和 Java 的相同示例

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

于 2013-03-01T14:19:37.583 回答
0

使用你自己的ThreadPoolExecutor而不是Executors. 然后覆盖afterExecuteTPE 提供的钩子,对异常做任何你想做的事情。

于 2013-03-01T15:05:44.753 回答
0

我在这里的字里行间读了一点,但看起来您想知道套接字上的初始侦听是否成功。如果您想等待并查看是否有任何客户端失败,则无需在不同的线程中运行它。

如果这是正确的,那么您可以在启动线程以处理客户端连接之前捕获初始 TCP 服务器套接字实例化发出的任何异常。将服务器传递给新线程,而不是在新线程中创建它。

于 2013-03-03T09:37:40.280 回答