首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >运行在Tomcat 9上的多线程服务器

运行在Tomcat 9上的多线程服务器
EN

Stack Overflow用户
提问于 2017-03-21 10:18:48
回答 1查看 742关注 0票数 0

我试着找一个问题来解决我的问题,但我所能找到的只是许多类似的问题,但没有答案来解决我的问题。

我正在为Tomcat创建一个java webapp,它还必须充当一个处理多个传入连接的TCP服务器:为此,我在一个单独的线程中运行TCP服务器代码,然后使用ExecutorService为每个连接创建线程。问题基本上是,当我停止Tomcat时,服务器线程永远不会停止(即使还没有人连接)并挂起Tomcat,直到我关闭任务管理器中的相关进程为止。

因此,这是该项目的起点:

代码语言:javascript
运行
复制
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类:

代码语言:javascript
运行
复制
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关闭时运行:

代码语言:javascript
运行
复制
@Override
public void contextDestroyed(ServletContextEvent sce) {
    serverThread.interrupt();
    tcpServer.close();
    ServletContextListener.super.contextDestroyed(sce); 
}

我做了那么多的编辑,试图实现我在互联网上找到的解决方案,这些代码中肯定有一些可能是多余的或无用的。有人能给我指点一下该怎么做才能正确地停止TCPServer线程吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-21 13:25:50

感谢this answer和Kayaman的评论,我修改了整个代码,并以某种方式使其正常工作。

init()覆盖相同,而contextDestroyed覆盖现在是

代码语言:javascript
运行
复制
@Override
public void contextDestroyed(ServletContextEvent sce) {        
    tcpServer.close();
    serverThread.interrupt();
    ServletContextListener.super.contextDestroyed(sce);
}

现在的TCPServer类是:

代码语言:javascript
运行
复制
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);
       }
   }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42924201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档