我试着找一个问题来解决我的问题,但我所能找到的只是许多类似的问题,但没有答案来解决我的问题。
我正在为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线程吗?
发布于 2017-03-21 13:25:50
感谢this answer和Kayaman的评论,我修改了整个代码,并以某种方式使其正常工作。
init()覆盖相同,而contextDestroyed覆盖现在是
@Override
public void contextDestroyed(ServletContextEvent sce) {
tcpServer.close();
serverThread.interrupt();
ServletContextListener.super.contextDestroyed(sce);
}
现在的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() {
try {
serverSocket = new ServerSocket(listeningPort);
while (!Thread.currentThread().isInterrupted()) {
Socket clientSocket = serverSocket.accept();
pool.submit(new ConnectionHandler(clientSocket));
}
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
} finally {
pool.shutdown();
}
}
private class ConnectionHandler implements Runnable {
private Socket sock;
public ConnectionHandler(Socket sock){
this.sock = sock;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try{
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = in.readLine();
System.out.println("Incoming: " + line);
sock.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void close(){
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
https://stackoverflow.com/questions/42924201
复制相似问题