简体   繁体   中英

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

I have a class which encapsulates a Server Socket ie a server functionality.
The interface of the class is:

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

the start is as follows:

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

I have trouble figuring out how I would start this without blocing my main .
I mean I need to start the server from a background thread so I thought of the following:

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

But what I want is to know that the server started and did not throw an exception. How can I do that?
Ie how can I know from my main thread that the background server started fine and so I can continue with the rest actions?

Start the server. Wait a bit. Try to connect to it on the local stack. If the connect succeeds, you have a winner - just close the temp connection.

A simple way of doing this would be to collect all exceptions in a collection and return them to the foreground thread at some point in time.

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();
    }    

}

Elaboration on how to transfer data between threads:

If you declared your server similarly to my suggestion above, then we can change the code you have used to spawn your server to transfer the serverStartupOk information:

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());
}

Here is a very simple example (though there are many better - and more complicated - ways):

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.
}

maybe you can implement an Event Handler into your main application. Your main application should be registered as eventlistener to your server class.

Please have a look at the following link, it shows you an example of event handling for C# and the same example for Java

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

Use your own ThreadPoolExecutor instead of the pre-baked ones in Executors . Then override the afterExecute hook provided by TPE to do whatever you want with the exceptions.

I'm reading a bit between the lines here, but it looks like you want to know if the initial listen on the socket succeeded or not. If you wanted to wait and see if any client failed, then there would be no need to run it in a different thread.

If that's correct, then you can catch any exceptions emitted by the initial TCP server socket instantiation before you start the thread to handle client connections. Pass the server in to the new thread, instead of creating it in the new thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM