我正在使用com.sun.net.httpserver.HttpServer创建一个小容器来测试服务器代码的位数,并且无法让它使用多个线程来处理请求。
我调用java.util.concurrent.Executors.newFixedThreadPool(20)来创建一个包含20个线程的java.util.concurrent.ThreadPoolExecutor。然后,我在HttpServer上设置了这个Executor。使用Jmeter,我触发20个客户端线程,发送请求路由到服务器中唯一的HttpHandler实现。该处理程序执行System.out.println(this),我看到了这个输出:
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
我以为我会在这里看到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 :(得分:2)
可以在不同的线程中多次运行runnable的相同实例。有关详细信息,请参阅Initializing two threads with the same instance of a runnable。
您在示例中打印的是HttpHandler信息,但没有关于在哪个线程中运行的信息。并且该信息不会更改,因为服务器始终为所有线程重用相同的对象。
如果要打印线程ID,可以使用:
long threadId = Thread.currentThread().getId();
System.out.println(threadId);
threadId应该按预期更改。