【发布时间】:2017-08-12 22:43:53
【问题描述】:
我试图找到一个涵盖我的问题的问题,但我只能找到很多类似的问题,但没有解决我问题的答案。
我正在为 Tomcat 创建一个 java webapp,除此之外,它还必须充当处理多个传入连接的 TCP 服务器:为此,我在单独的线程中运行 TCP 服务器代码,该线程又使用一个 ExecutorService 为每个连接创建线程。问题基本上是,当我停止 Tomcat 时,服务器线程永远不会停止(即使还没有人连接)并挂起 Tomcat,直到我在任务管理器中关闭相关进程。
所以,这是程序的起点:
private TCPServer tcpServer;
Thread serverThread;
@Override
public void init() throws ServletException {
DBConn = getDBConn();
if (DBConn != null) {
//initiates loggers, reads configurations from a file, etc
//starts TCP server
tcpServer = new TCPServer(50001, 200);
serverThread = new Thread(tcpServer);
serverThread.start();
//will be doing other stuff
} else {
//handles DB connection failure
}
}
这是 TCPServer 类:
public class TCPServer implements Runnable {
private final int listeningPort;
PrintWriter out;
BufferedReader in;
ServerSocket serverSocket;
private final ExecutorService pool;
public TCPServer(int port, int poolSize) {
listeningPort = port;
pool = Executors.newFixedThreadPool(poolSize);
}
@Override
public void run() {
LinkedBlockingQueue<Socket> queue = new LinkedBlockingQueue<>();
try {
serverSocket = new ServerSocket(listeningPort);
while (!Thread.currentThread().isInterrupted()) {
pool.execute(new ConnectionHandler(queue));
queue.put(serverSocket.accept());
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
private class ConnectionHandler implements Runnable {
private LinkedBlockingQueue<Socket> socketQueue;
public ConnectionHandler(LinkedBlockingQueue<Socket> queue) {
this.socketQueue = queue;
}
@Override
public void run() {
while (!Thread.interrupted() || !Thread.currentThread().isInterrupted()) {
try (Socket clientSocket = socketQueue.take()) {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = in.readLine();
System.out.println("Incoming: " + line);
clientSocket.close();
} catch (InterruptedException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void close(){
Thread.currentThread().interrupt();
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex); }
pool.shutdownNow();
}
}
我在主类(与上面的 init() 相同)中添加了这个覆盖,它在 Tomcat 关闭时运行:
@Override
public void contextDestroyed(ServletContextEvent sce) {
serverThread.interrupt();
tcpServer.close();
ServletContextListener.super.contextDestroyed(sce);
}
为了实现我在互联网上找到的解决方案,我进行了很多编辑,因此肯定有些代码可能是多余的或无用的。 有人可以指点我应该怎么做才能正确停止 TCPServer 线程吗?
【问题讨论】:
-
在已经是一个TCP服务器的Tomcat里面放一个TCP服务器不是很聪明。你确定你已经关闭了执行者池吗?此外,尝试调试代码是非常烦人的,这是“我尝试将所有内容粘贴到互联网上但没有任何效果,我不知道自己在做什么”的结果。
-
你说得对,但今天早上我很绝望。无论如何,你的评论给了我力量,我几乎从头开始清理代码......现在它似乎正在工作。你认为发布工作代码值得吗?
-
当然,将其作为答案发布,然后您可以接受它,这可以被视为“封闭”问题。
标签: java multithreading tomcat tcp server