Java try-with-resources 卡住了

Posted

技术标签:

【中文标题】Java try-with-resources 卡住了【英文标题】:Java try-with-recourses stuck 【发布时间】:2017-05-09 13:23:01 【问题描述】:

我有一个经典的服务器多客户端程序。服务器监听 ServerSocket 并为每个传入的套接字构建一个新的 Runnable 类并在 ExecuteService 中执行它。

在 Runnable 类的 run 方法中,我打开 try-with-resources 块,在 try 中我有一个 while 循环,它从 inputstream 读取并写入 outputstream,直到它收到来自客户端的 FIN 命令。一切正常,客户端成功断开连接。运行到达 finally 块并打印一些用于测试的东西,但它没有退出 try 块,因此它没有退出 run 方法,我被困在 run 的某个地方,可能是输入流的 read 方法。

如果有人感兴趣,我可以发布代码。

如何强制关闭 finally 中的所有内容并退出 run 方法?

代码: 服务器.java:

public static void main(String[] args) 
    playersReady = new ArrayList<Integer>();
    ServerSocket server = null;
    try 
        server = new ServerSocket(Consts.PORT);
        ExecutorService service = Executors.newFixedThreadPool(characters.size());
        while(playersReady.size()<characters.size())
            RequestHandler handler = new RequestHandler(server.accept());
            service.execute(handler);
        
        service.shutdownNow();
        service.shutdown();
        while(!service.isTerminated())

        System.out.println("finished");

RequestHandler.java

public final class RequestHandler implements Runnable 

    .....

public void run() 
    //DataOutputStream output = null;
    //DataInputStream input = null;

    try (DataOutputStream output = new DataOutputStream(socket.getOutputStream());
            DataInputStream input = new DataInputStream(socket.getInputStream()))
        // socket.setSoTimeout(500);
        handleReady(input.readUTF().split(" "), output);
        while (/*!shutdown && !socket.isClosed() && */socket.isConnected()) 

            System.out.println("check before read " + character.getId());
            String request = input.readUTF();
            System.out.println("check after read " + character.getId());

            System.out.println("-----------------------------------" + request);
            if (shutdown) 
                socket.shutdownInput();
                socket.getOutputStream().flush();
                socket.shutdownOutput();
                break;
            
            String[] requestParser = request.split(" ");
            if (requestParser[1].equals("DMG")) 
                // handle damage request
                handleDamage(requestParser, output);
             else if (requestParser[1].equals("BND")) 
                // handle bandage request
                handleBandage(requestParser, output);
             else if (requestParser[1].equals("FIN")) 
                // handle finish request
                handleFin();
                if (!socket.isClosed())
                    socket.shutdownInput();
                if (!socket.isClosed()) 
                    socket.getOutputStream().flush();
                    socket.shutdownOutput();
                
                shutdown = true;
                break;
             else 
                break;
            
        
     catch (SocketTimeoutException e) 
        System.out.println(e.getMessage());
     catch (IOException e) 
        e.printStackTrace();
        shutdown = true;
        break;
     catch (Throwable e) 
        e.printStackTrace();
     finally 
        try 
            System.out.println("finished");

            if (!socket.isClosed())
                socket.shutdownInput();
            if (!socket.isClosed()) 
                socket.getOutputStream().flush();
                socket.shutdownOutput();
                socket.close();
            
            socket.close();
         catch (IOException e) 
            e.printStackTrace();
        
    
    System.out.println("Done run");

....


finally 中的System.out.println("finished") 被打印出来, 但是run方法末尾的System.out.println("Done run")没有!!

为什么? 它卡在 run 方法中,我认为是在 readUTF 调用中,但我关闭了所有资源!

【问题讨论】:

你试过调试你的程序吗?您的“我认为在 readUTF 调用中”有点含糊。 我试过了,没什么特别的,它通过了run方法,上到java的Runnable类并停止,但线程继续运行 【参考方案1】:

您在该行之前返回,这就是它没有运行的原因。 finally 块无论如何都会运行,因为它是一个 finally 块。 finally 块总是运行,这条规则只有一个例外:System.exit(),但事实并非如此。

【讨论】:

哪一行? run 方法运行完美,它只是不会停止,也不会停止关联的线程 哦,我明白了,我将每个“return”语句都更改为“break”。它现在打印最终的打印命令,但线程并没有停止,我的意思是它不会继续服务器的运行方法

以上是关于Java try-with-resources 卡住了的主要内容,如果未能解决你的问题,请参考以下文章

java中的try-with-resources和return语句

Java 7 使用TWR(Try-with-resources)完成文件copy

java遗珠之try-with-resources

java遗珠之try-with-resources

java 7新特性-TWR(Try-with-resources)

[Java开发之路](20)try-with-resource 异常声明