2013-08-06 25 views
5

我正在使用com.sun.net.httpserver.HttpServer創建一個小容器來測試多個服務器代碼,並且無法讓它使用多個線程來處理請求。如何讓HttpServer並行創建多個HttpHandler?

我調用java.util.concurrent.Executors.newFixedThreadPool(20)創建一個具有20個線程的java.util.concurrent.ThreadPoolExecutor。然後,我在HttpServer上設置這個Executor。使用Jmeter,我關閉了20個客戶線程,發送一個請求被路由到服務器中唯一的HttpHandler實現。該處理程序做了的System.out.println(本),我看到這樣的輸出:

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] 
http[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

我以爲我會看到20(或接近20)在這裏被使用不同的線程。這是代碼。

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

我想讓HttpServer並行創建多個TestHandler來爲多個同時請求提供服務。我在這裏錯過了什麼?

(順便說一句,這是非常相似Can I make a Java HttpServer threaded/process requests in parallel?,雖然這個問題的答案是使用一個Executor,這我已經在做的事情。謝謝。)

+0

是否有可能每個請求處理得足夠快,執行程序能夠繼續重用同一個線程?你可以在你的處理程序中添加一些延遲來查看是否有任何改變? – elevine

+0

@elevine:我想到了,所以在TestHandler.handle(HttpExchange)中添加了一個'Thread.sleep(1000)'。同樣的結果。謝謝。 – Michael

回答

2

可運行的同一個實例可以在多次運行不同的線程。有關更多信息,請參閱Initializing two threads with the same instance of a runnable

你在你的例子中打印的是HttpHandler的信息,但沒有關於哪個線程正在運行。並且該信息不會隨服務器對所有線程重複使用始終相同的對象而發生更改。

如果你想打印線程ID,您可以使用:如預期

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

的threadId應該改變。