【问题标题】:Unable to read from the Socket Input Stream in a multithreaded environment with wait and notify无法在等待和通知的多线程环境中从套接字输入流中读取
【发布时间】:2010-01-29 15:22:42
【问题描述】:

我使用 2 个线程 - ReaderThread 用于读取 Socket 输入流,而 WriterThread 用于写入套接字输出流。当我只是写入流而不是从流中读取时,它们都可以正常工作。但是,当我还从输入流中读取时,程序不会进一步运行,它会挂起。

下面是编写的代码——它在 WriterThread 类中。

try{
        Scanner consoleReader = new Scanner(System.in);
        String inst="";
        PrintWriter writer = new PrintWriter(client.getOutputStream(),true);
        while(true){
                synchronized(response){


                    System.out.print("Enter something: ");
                    System.out.flush();

                    inst=consoleReader.nextLine();
                    System.out.println(inst);
                    instruction.setInstruction(inst);
                    if(!instruction.getInstruction().equals("")){

                        writer.print(instruction.getInstruction());
                        writer.flush();
                        response.notifyAll();   

                        if(instruction.getInstruction().equalsIgnoreCase("end")){
                            break;
                        }
                        response.wait();

                    }
                }//End of response sync
        }//End of while
        }catch(IOException ioex){
            System.out.println("IO Exception caught in Writer Thread");
        }catch(InterruptedException iex){
            System.out.println("Writer thread interrupted");
        } 

以上代码- 从命令行读取,使用“writer”对象将其写入套接字输出流。

下面是从流中读取的代码——它在 ReaderThread 类中

try{        
        Scanner reader = new Scanner(client.getInputStream());
        String txtRead="";
        outer:
        while(true){
            synchronized(response){
                response.wait();
                System.out.println("Reader Running");

                while(reader.hasNext()){ //Line-Beg
                    txtRead=reader.next();
                    System.out.println("Received: "+txtRead);
                    if(txtRead.equalsIgnoreCase("end")){
                        response.notifyAll();
                        break outer;
                    }
                }//End of reader while, Line-End

                response.notifyAll();
            }//End of response sync
        }//End of while
        }catch(IOException ioex){
            System.out.println("IOException caught in ReaderThread");
        }
        catch(InterruptedException iex){
                System.out.println("Interrupted ReaderThread");
        }  

上面的代码从 Socket 的输入流中读取数据。上面代码的问题是它在打印后无限期地等待 - “Reader Running”。但是当我注释掉从 Line-Beg 到 Line-End 的代码时,它会正确执行,让其他 WriterThread 有机会写入输出流。为什么会这样?

注意:“响应”是用于同步的通用对象。一旦主要方法完成执行,我也会关闭“服务器套接字”。客户端套接字也是“C”套接字。

我没有发现正在使用的 notify() 和 wait() 方法有问题。

【问题讨论】:

    标签: java multithreading sockets


    【解决方案1】:

    reader.hasNext() 在持有response 对象锁的同时阻塞,直到套接字输入流中的某些输入可用。这可以防止编写器线程获取response 锁并写入套接字输出流。为什么要在同一个锁上同步读取器和写入器线程?对我来说似乎没有必要。

    【讨论】:

    • 我尝试在 Socket 输入流上发送一些数据,但没有成功。实际上我认为是这样的——编写器写入套接字的 o/p 流并通知读取器线程开始读取可用数据。在阅读器完成其阅读后,它会等待作者线程写一些东西。所以一个人必须阻止自己,直到其他人完成它的任务。
    • 其实你为什么要同步呢?受保护的共享资源是什么?
    • 我的想法是在执行另一个动作时阻止一个动作。就像在读取数据时,应用程序不应写入任何内容,反之亦然。
    • 您可以在写入的同时从套接字读取。不需要同步。尝试删除同步块并等待/通知调用,一切都应该正常。
    • 非常感谢。我在想,如果两者同时执行,那么可能会读取一些错误或不相关的数据。
    猜你喜欢
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 2014-08-28
    • 2021-12-16
    相关资源
    最近更新 更多