I'm using com.sun.net.httpserver.HttpServer to create a small container for testing bits of server code and am having trouble getting it to use more than one thread to handle requests.
I call java.util.concurrent.Executors.newFixedThreadPool(20) to create a java.util.concurrent.ThreadPoolExecutor with 20 threads. Then, I set this Executor on the HttpServer. Using Jmeter, I fire off 20 client threads to send a request to be routed to the only HttpHandler implementation in the server. That handler does a System.out.println(this) and I'm seeing this output:
Started TestServer at port 8800
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
http.TestHandler@30eb9dfa
I thought I would see 20 (or nearly 20) different threads being used here. Here's the code.
package http;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class TestServer implements Runnable {
    private final static int PORT    = Integer.getInteger("test.port", 8800); 
    private static TestServer serverInstance;
    private HttpServer        httpServer;
    private ExecutorService   executor;
    @Override
    public void run() {
        try {
            executor = Executors.newFixedThreadPool(20);
            httpServer = HttpServer.create(new InetSocketAddress(PORT), 0);
            httpServer.createContext("/test", new TestHandler());
            httpServer.setExecutor(executor);
            httpServer.start();
            System.out.println("Started TestServer at port " + PORT);
            // Wait here until notified of shutdown.
            synchronized (this) {
                try {
                    this.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
    static void shutdown() {
        try { 
            System.out.println("Shutting down TestServer.");            
            serverInstance.httpServer.stop(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        synchronized (serverInstance) {
            serverInstance.notifyAll();
        }
    }
    public static void main(String[] args) throws Exception {
        serverInstance = new TestServer();
        Thread serverThread = new Thread(serverInstance);
        serverThread.start();
        Runtime.getRuntime().addShutdownHook(new OnShutdown());
        try {
            serverThread.join();
        } catch (Exception e) { }
    }
}
/* Responds to the /test URI. */
class TestHandler implements HttpHandler {
    boolean debug = Boolean.getBoolean("test.debug");
    public void handle(HttpExchange exchange) throws IOException {
        System.out.println(this);  // ALWAYS SAME THREAD!
        String response = "RESPONSE AT " + System.currentTimeMillis();
        exchange.sendResponseHeaders(200, response.length());
        OutputStream os = exchange.getResponseBody();
        os.write(response.getBytes());
        os.flush();
        os.close();
    }
}
/* Responds to a JVM shutdown by stopping the server. */
class OnShutdown extends Thread {
    public void run() {
        TestServer.shutdown();
    }
}
I'd like the HttpServer to create multiple TestHandlers in parallel to service the multiple simultaneous requests. What am I missing here?
(BTW, this is quite similar to Can I make a Java HttpServer threaded/process requests in parallel?, though the answer to that is to use an Executor, which I am already doing. thanks.)