2013-08-06 9 views
5

Sto usando com.sun.net.httpserver.HttpServer per creare un piccolo contenitore per testare bit di codice server e sto avendo problemi a farlo utilizzare più di un thread per gestire le richieste.Come ottenere HttpServer per creare più HttpHandler in parallelo?

Ho chiamato java.util.concurrent.Executors.newFixedThreadPool (20) per creare un java.util.concurrent.ThreadPoolExecutor con 20 thread. Quindi, ho impostato questo Executor su HttpServer. Usando Jmeter, sparo 20 thread client per inviare una richiesta da instradare all'unica implementazione HttpHandler nel server. Che fa un gestore System.out.println (questo) e sto vedendo questa uscita:

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] 

ho pensato che avrei visto 20 (o quasi 20) diversi thread in uso qui. Ecco il codice.

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

Mi piacerebbe che HttpServer crei più TestHandler in parallelo per soddisfare le richieste multiple simultanee. Cosa mi manca qui?

(a proposito, questo è abbastanza simile a Can I make a Java HttpServer threaded/process requests in parallel?, anche se la risposta a questo è quello di utilizzare un esecutore, che sto già facendo. Grazie.)

+0

È possibile che ogni richiesta sia gestita abbastanza velocemente dove l'esecutore è in grado di continuare a riutilizzare lo stesso thread? Puoi aggiungere qualche ritardo al tuo gestore per vedere se qualcosa cambia? – elevine

+0

@elevine: ci ho pensato, quindi ho aggiunto un 'Thread.sleep (1000)' a TestHandler.handle (HttpExchange). Stesso risultato Grazie. – Michael

risposta

2

la stessa istanza di un eseguibile può essere eseguito più volte in fili diversi Vedi Initializing two threads with the same instance of a runnable per maggiori informazioni.

Quello che stai stampando nel tuo esempio è l'informazione HttpHandler ma nulla su quale thread è in esecuzione. E quell'informazione non cambia mentre il server riutilizza sempre lo stesso oggetto per tutti i thread.

Se si desidera stampare solo l'ID è possibile utilizzare:

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

ThreadID dovrebbe cambiare come previsto.

Problemi correlati