10.6 Using Executor as a Service
While Executor on its own is a
great addition to Java, there are times when you need more control over how execution occurs, when it stops,
and even how it stops. For all of these cases, ExecutorService should be used.
10.6.1 How do I do that?
If you take a close look at the factory method signatures for Executors,
you'll note that each returns an ExecutorService, rather than an
Executor. java.util.concurrent.ExecutorService is a subinterface of
Executor, and adds a good deal of functionality to the simple execute( )
method you saw in "Separating Thread Logic From Execution." Two of
these are key in allowing you to stop an ExecutorService, either for an
error condition or in a normal shutdown situation:NOTEThis isn't a fully (or even partially) functional FTP server, and is just
used for example purposes. You won't find it in the sample code, as it doesn't actually
work.
NOTEBasically, getSocket( ) would wait for a client to connect, and
public class FtpServer {
private ExecutorService service;
public FtpServer(int port) throws IOException {
openSocket(port);
service = Executors.newFixedThreadPool(100);
}
public void go( ) {
try {
while (true) {
service.execute(new FtpHandler(getSocket( )));
}
} catch (Exception e) {
service.shutdownNow( );
}
}
public void stop( ) {
try {
service.shutdown( );
} catch (Exception e) {
// report problem
}
}
}
class FtpHandler implements Runnable {
private Socket socket;
public FtpHandler(Socket socket) {
this.socket = socket;
}
public void run( ) {
// Handle connection
}
}
return the connection to that client as a Socket object.This little pseudo-class primarily illustrates two methods:
shutdown( )
This method stop the service, but first allows the service to attempt
to complete all running and queued tasks. No new tasks are accepted
after this call, though.
shutdownNow( )
A little more direct, this method stops the service, and does not allow any queued or running tasks to execute. Currently running tasks are basically tossed, and queued tasks are returned via a
List<Runnable>, for program use (if desiredin the example, I
ignored these completely).
You can choose whichever of these suits you, based on your application
needs. There's one other big advantage of using ExecutorService, which
the next lab, Using Callable Objects, looks at in detail.