Adding a Thread Pool to a Server

Multi-threading is a good thing but it's still not a perfect solution. For example, let's take a look at the accept loop of the ThreadedEchoServer:

     while (true) {
        try {
          Socket s = ss.accept();
          ThreadedEchoServer tes = new ThreadedEchoServer(s);
          tes.start();
        }
        catch (IOException ex) {
        }

Every time you pass through this loop, a new thread gets created. Every time a connection is finished the thread is disposed of. Spawning a new thread for each connection takes a non-trivial amount of time, especially on a heavily loaded server. It would be better not to spawn so many threads.

An alternative approach is to create a pool of threads when the server launches, store incoming connections in a queue, and have the threads in the pool progressively remove connections from the queue and process them. This is particularly simple since the operating system does in fact store the incoming connections in a queue. The main change you need to make to implement this is to call accept() in the run() method rather than in the main() method. The program below demonstrates.

import java.net.*;
import java.io.*;


public class PoolEchoServer extends Thread {

  public final static int defaultPort = 2347;
  ServerSocket theServer;
  static int numberOfThreads = 10;
  
  
  public static void main(String[] args) {
  
    int port = defaultPort;
    
    try {
      port = Integer.parseInt(args[0]);
    }
    catch (Exception ex) {
    }
    if (port <= 0 || port >= 65536) port = defaultPort;
    
    try {
      ServerSocket ss = new ServerSocket(port);
      for (int i = 0; i < numberOfThreads; i++) {
        PoolEchoServer pes = new PoolEchoServer(ss); 
        pes.start();
      }
    }
    catch (IOException ex) {
      System.err.println(ex);
    }

  }
  
  public PoolEchoServer(ServerSocket ss) {
    theServer = ss;
  }
  
  public void run() {
  
    while (true) {
      try {
        Socket s = theServer.accept();
        OutputStream out = s.getOutputStream();
        InputStream in = s.getInputStream();
        while (true) {
          int n = in.read();
          if (n == -1) break;
          out.write(n);
          out.flush();
        } // end while
      } // end try
      catch (IOException ex) {
      }       
    } // end while
    
  } // end run
    
}

In the program above the number of threads is set to ten. This can be adjusted for performance reasons. How would you go about testing the performance of this program relative to the one that spawns a new thread for each connection? How would you determine the optimum number of threads to spawn?


Previous | Next | Top | Cafe au Lait

Copyright 1999 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified June 30, 1999