我在Java SE中编写了一个简单的Web服务器,没有使用任何API。它有一个GUI,您可以在其中启动/停止服务器并查看它使用的线程数。
我们老师的一个要求是它必须支持多线程,你可以在启动服务器之前控制最大线程。
我有WebServer
类扩展Thread
并且它作为一个线程运行。它有字段MAX_THREADS和thread_counter。
Web服务器:
public static final int MAX_THREADS = 5;
public static int threads_counter = 0;
public void run() {
while (isRunning) {
try {
Socket socket = _serverSocket.accept();
if (threads_counter >= MAX_THREADS) {
Thread.sleep(100);
System.out.println("OVERLOAD");
} else {
new Handler(socket, new File(rootDir)).start();
}
} catch (IOException ex) {
Logger.getLogger(WebServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(WebServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Handler类也扩展了Thread
。我想将Handler
的数量限制为MAX_THREADS。
以下是Handler的观点:
public void run() {
synchronized (WebServer.class) {
WebServer.threads_counter++;
}
this.setName("thread no. " +WebServer.threads_counter);
System.out.println(this.getName());
HandleRequest(_socket);
synchronized (WebServer.class) {
WebServer.threads_counter--;
}
}
然而,这并不总是按预期工作。有时,它的启动时间超过MAX_THREADS Handler
,我不知道如何解决它。
你能帮我解决一下情况吗?
答案 0 :(得分:3)
我建议使用ExecutorService而不是手动创建线程,更具体地说是Executors.newFixedThreadPool。
这样,您就可以更好地控制执行。
另一方面,在当前代码中,用AtomicInteger替换synchronized块并增加静态变量。
在业余时间,看看java.util.concurrent包,它包含许多可用于多线程的好东西。
答案 1 :(得分:1)
您在threads_counter
块之外使用synchronized
,此字段不易变:您无法保证阅读"真实"价值threads_counter
。
但是,正如评论/答案中所述,您不应该自己创建线程,而是使用ThreadPool
或ExecutorService
。重用这些工具而不是重新实现它总是更好。