2013-08-06 5 views
5

Używam com.sun.net.httpserver.HttpServer do utworzenia małego kontenera do testowania bitów kodu serwera i mam problem z uzyskaniem go do używania więcej niż jednego wątku do obsługi żądań.Jak uzyskać HttpServer do tworzenia wielu HttpHandlers równolegle?

Wywołuję java.util.concurrent.Executors.newFixedThreadPool (20), aby utworzyć element java.util.concurrent.ThreadPoolExecutor z 20 wątkami. Następnie ustawiam Executor na HttpServer. Korzystając z Jmetera, odpalam 20 wątków klienta, aby wysłać żądanie do routingu do jedynej implementacji HttpHandler na serwerze. Że teleskopowa robi System.out.println (this) i widzę to wyjście:

Started TestServer at port 8800 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

myślałem, że chciałbym zobaczyć 20 (czyli prawie 20) różne wątki używane są tutaj. Oto kod.

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

Chciałbym HttpServer stworzyć wiele TestHandlers równolegle do obsługi wielu jednoczesnych żądań. Czego tu mi brakuje?

(BTW, to jest całkiem podobny do Can I make a Java HttpServer threaded/process requests in parallel?, choć odpowiedź na to jest użycie wykonawca testamentu, który ja już robi. Dzięki.)

+0

Czy jest możliwe, że każde żądanie jest obsługiwane wystarczająco szybko, gdy wykonawca jest w stanie ponownie używać tego samego wątku? Czy możesz dodać trochę opóźnienia do swojego programu obsługi, aby sprawdzić, czy coś się zmieni? – elevine

+0

@elevine: Myślałem o tym, więc dodano 'Thread.sleep (1000)' do TestHandler.handle (HttpExchange). Ten sam wynik. Dzięki. – Michael

Odpowiedz

2

To samo wystąpienie runnable można uruchomić wiele razy różne wątki. Aby uzyskać więcej informacji, patrz Initializing two threads with the same instance of a runnable.

To, co drukujesz w twoim przykładzie, to informacje HttpHandler, ale nic o tym, w którym wątku jest uruchomiony. Informacje te nie zmieniają się, ponieważ serwer wykorzystuje zawsze ten sam obiekt dla wszystkich wątków.

Jeśli chcesz wydrukować id wątku można użyć:

long threadId = Thread.currentThread().getId(); 
System.out.println(threadId); 

ThreadID należy zmienić zgodnie z oczekiwaniami.

Powiązane problemy