图书馆系统开发:如何让PrintWriter无需等待输入执行后续方法?
问题背景与描述
我开发了一个和MySQL交互的图书馆系统,客户端和服务器通过PrintWriter(变量名out)和Scanner进行通信。现在的问题是,服务器在发送完查询结果后,没法跳出等待输入的循环,没办法自动执行bookStoreMenu()方法。
我试过加换行符\n,但PrintWriter好像不生效;也尝试过在客户端和服务器用各种循环、布尔判断,都没解决问题。
客户端代码
socket = new Socket(IPaddress, port); System.out.println("Connected to server at "+ IPaddress + ":" + port); //Connect a Scanner to the socket's InputStream to read lines from it in = new Scanner(socket.getInputStream()); //Connect a PrintWriter to the OutputStream to send lines to server out = new PrintWriter(socket.getOutputStream(), true); //Connect a Scanner to system input to take command line instructions menu(); userInput = new Scanner(System.in); while(userInput.hasNext()){ out.println(userInput.nextLine());//handle output to server System.out.println(in.nextLine()); //print input from server }
服务器代码片段
while (sqlExecute.next()) { int id = sqlExecute.getInt("bookID"); String isbn = sqlExecute.getString("book_ISBN"); String title = sqlExecute.getString("book_title"); String author = sqlExecute.getString("book_author"); String publisher = sqlExecute.getString("book_publisher"); String language = sqlExecute.getString("book_language"); //Building a string /*BookString = ("Book ISBN: " + isbn + ", Book Title: " + title + ", Author: " + author + ", Publisher: " + publisher + ", Language " + language);*/ bookResults.append("BookID: " +id + ", Book ISBN: " + isbn); bookResults.append(", Title: " + title + ", Author: " + author); bookResults.append(", Publisher: " + publisher + ", Language: " + language); bookResults.append(" || "); System.out.printf("%s, %s, %s, %s, %s, %s\n", id, isbn, title, author, publisher, language + "\n"); } //Sending results out.println(bookResults + "\n"); bookStoreMenu();
解决方案
1. 定义通信边界:添加响应结束标记
问题核心是客户端和服务器的通信没有明确的结束信号,导致一方一直阻塞等待。你需要约定一个特殊字符串作为响应结束标记,让客户端知道当前批次的消息已发送完毕,避免卡在in.nextLine()。
修改服务器代码,发送完结果后追加结束标记:
//Sending results out.println(bookResults.toString()); out.println("END_OF_RESPONSE"); // 新增结束标记 bookStoreMenu();
同步修改客户端循环逻辑,判断到结束标记就停止读取服务器响应:
userInput = new Scanner(System.in); while(userInput.hasNext()){ out.println(userInput.nextLine());//handle output to server // 循环读取直到收到结束标记 String serverMsg; while (!(serverMsg = in.nextLine()).equals("END_OF_RESPONSE")) { System.out.println(serverMsg); } }
2. 修复服务器的阻塞逻辑
你提供的服务器代码只展示了查询结果发送部分,推测服务器存在一个等待客户端输入的循环(比如用Scanner读取socket输入)。如果服务器一直卡在等待客户端指令的逻辑里,bookStoreMenu()就无法执行。
可以用多线程分离客户端请求处理和菜单逻辑,避免互相阻塞:
// 服务器接受连接后,启动独立线程处理客户端交互 new Thread(() -> { Scanner in = new Scanner(socket.getInputStream()); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // 处理客户端请求的循环 while (in.hasNextLine()) { String clientCmd = in.nextLine(); // 执行你的MySQL查询逻辑(即你提供的那段结果拼接代码) // ... // 发送结果和结束标记 out.println(bookResults.toString()); out.println("END_OF_RESPONSE"); // 直接执行菜单方法,无需等待输入 bookStoreMenu(); } }).start();
3. 修正PrintWriter的换行使用
out.println()方法会自动添加系统对应的行分隔符,不需要手动拼接"\n"。你创建PrintWriter时已经开启了自动刷新(第二个参数为true),所以每次调用println()都会立即把内容发送出去,不用担心缓冲区阻塞问题。直接用out.println(bookResults.toString())即可,多余的"\n"反而可能导致解析混乱。
内容的提问来源于stack exchange,提问作者Dfr444er
相关产品推荐
相关产品推荐

