2323import java .io .IOException ;
2424import java .util .concurrent .TimeUnit ;
2525import java .util .logging .Logger ;
26+ import java .util .concurrent .ExecutorService ;
27+ import java .util .concurrent .Executors ;
2628
2729/**
2830 * Server that manages startup/shutdown of a {@code Greeter} server.
@@ -31,11 +33,20 @@ public class HelloWorldServer {
3133 private static final Logger logger = Logger .getLogger (HelloWorldServer .class .getName ());
3234
3335 private Server server ;
34-
3536 private void start () throws IOException {
3637 /* The port on which the server should run */
3738 int port = 50051 ;
39+ /*
40+ * By default gRPC uses a global, shared Executor.newCachedThreadPool() for gRPC callbacks into
41+ * your application. This is convenient, but can cause an excessive number of threads to be
42+ * created if there are many RPCs. It is often better to limit the number of threads your
43+ * application uses for processing and let RPCs queue when the CPU is saturated.
44+ * The appropriate number of threads varies heavily between applications.
45+ * Async application code generally does not need more threads than CPU cores.
46+ */
47+ ExecutorService executor = Executors .newFixedThreadPool (2 );
3848 server = Grpc .newServerBuilderForPort (port , InsecureServerCredentials .create ())
49+ .executor (executor )
3950 .addService (new GreeterImpl ())
4051 .build ()
4152 .start ();
@@ -48,7 +59,12 @@ public void run() {
4859 try {
4960 HelloWorldServer .this .stop ();
5061 } catch (InterruptedException e ) {
62+ if (server != null ) {
63+ server .shutdownNow ();
64+ }
5165 e .printStackTrace (System .err );
66+ } finally {
67+ executor .shutdown ();
5268 }
5369 System .err .println ("*** server shut down" );
5470 }
0 commit comments