Java-readLine()阻塞問題及解決過程
更新時間:2026年05月07日 08:30:36 作者:昫 灬
文章主要討論了socket編程中readLine()方法的阻塞問題,在使用readLine()接收消息時,如果沒有換行符,則會一直阻塞,解決方法是在發(fā)送消息時添加換行符,或者為每個客戶端創(chuàng)建獨立的轉(zhuǎn)發(fā)線程
socket編程中readLine()阻塞問題
readLine()的API說明
- public String readLIne() throws IOException
中文版:
- 讀一行文字。 一行被視為由換行符(’\ n’),回車符(’\ r’)中的任何一個或隨后的換行符終止。
- 返回:包含行的內(nèi)容的字符串,不包含任何行終止字符,如果到達流末尾,則為null
英文版:
- Reads a line of text. A line is considered to be terminated by any one of a line feed (’\n’), a carriage return (’\r’), or a carriage return followed immediately by a linefeed.
- Returns:
- A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
遇到的問題:
- 當(dāng)使用socket寫一個雙向通信的服務(wù)端時,總是接收不到來自用戶的消息,和書上比對才發(fā)現(xiàn)是readLine()的問題,
- 還有就是客戶端和服務(wù)端的初始狀態(tài)問題(一個為初始為“發(fā)送”,一個為“接收”)
第一種情況
- 一個客戶端,一個服務(wù)端。當(dāng)服務(wù)端使用
readLine()讀消息時,需要讀到一個換行符(‘\n’,或’\r’)才會結(jié)束。否則回一直阻塞,主線程就掛在這兒了 - 解決方法:在客戶端發(fā)送消息的時候,外加一個換行符
//用戶發(fā)送消息的線程
class SentMessage extends Thread{
private Socket socket;
private BufferedWriter bw;
private BufferedReader mysc;
SentMessage(Socket socket){
this.socket = socket;
try {
bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
mysc = new BufferedReader(new InputStreamReader(System.in));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run(){
try{
while (true){
String mymessage = mysc.readLine();
bw.write(mymessage+"\n");
bw.flush();
if("bye".equals(mymessage)){
break;
}
}
}catch (IOException e){
e.printStackTrace();
}finally {
try{
if(mysc!=null){
mysc.close();
}
if(bw!=null){
bw.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
第二種
- 當(dāng)用服務(wù)器轉(zhuǎn)發(fā)來自每個用戶的消息到聊天室時,如果就用一個"轉(zhuǎn)發(fā)消息"方法也會出現(xiàn)問題,就是使用了readLine()的阻塞
- 思考:一個客戶都應(yīng)有一個自己”轉(zhuǎn)發(fā)消息“通道(線程),不和其他客戶共用一個”轉(zhuǎn)發(fā)通道“(會導(dǎo)致阻塞
- 解決,用一個線程來做轉(zhuǎn)發(fā)
//內(nèi)置線程類用于接收消息,并廣播
class AcceptMessage extends Thread{
private Socket clientsocket;
private BufferedReader br;
AcceptMessage(Socket clientsocket){
this.clientsocket = clientsocket;
}
/**
* 服務(wù)器將所有接收的消息廣播(顯示在每一個客戶的聊天窗口中
* 注意:如果這里不用線程,會出現(xiàn)問題,思考---其實就是readLine()阻塞的問題
*/
private void tellEveryone(Socket socket){
try{
//先從發(fā)送消息的客戶讀內(nèi)容
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = br.readLine();
chatArea.append("用戶"+socket.getPort()+": "+message+"\n");
//然后將內(nèi)容廣播到每一個客戶接口
Iterator<Socket> it = list.iterator();
while (it.hasNext()){
Socket socket2 = it.next();
//對自己就不要廣播了
if(socket!=socket2){
bw = new BufferedWriter(new OutputStreamWriter(socket2.getOutputStream()));
bw.write(socket2.getInetAddress().getHostAddress()+": "+message+"\n");
bw.flush();
}
}
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void run(){
while (true){
//接收并廣播
tellEveryone(clientsocket);
}
}
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java?@Mapper?使用注解的方式注入SQL的詳細(xì)過程
文章主要介紹了MySQL的JSON數(shù)據(jù)類型及其使用方法,包括在表中存儲和處理JSON數(shù)據(jù)、使用JSON數(shù)據(jù)進行復(fù)雜查詢以及在SQL語句中處理JSON數(shù)據(jù)的示例,感興趣的朋友跟隨小編一起看看吧2025-12-12
Java Spring分別實現(xiàn)定時任務(wù)方法
這篇文章主要為大家詳細(xì)介紹了Java與Spring設(shè)置動態(tài)定時任務(wù)的方法,定時任務(wù)的應(yīng)用場景十分廣泛,如定時清理文件、定時生成報表、定時數(shù)據(jù)同步備份等2022-07-07
JavaMap兩種遍歷方式keySet與entrySet詳解
這篇文章主要介紹了JavaMap兩種遍歷方式keySet與entrySet,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
AsyncHttpClient exception異常源碼流程解析
這篇文章主要為大家介紹了AsyncHttpClient的exception源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12
Java中的@RequiredArgsConstructor注解詳解
這篇文章主要介紹了Java中的@RequiredArgsConstructor注解詳解,@RequiredArgsConstructor是Lombok的一個注解,簡化了我們對@Autowired書寫,@RequiredArgsConstructor注解可以代替@Autowired注解,需要的朋友可以參考下2024-01-01
Spring?Boot?整合持久層之Spring Data JPA
在介紹Spring Data JPA的時候,我們首先認(rèn)識下Hibernate。Hibernate是數(shù)據(jù)訪問解決技術(shù)的絕對霸主,使用O/R映射技術(shù)實現(xiàn)數(shù)據(jù)訪問,O/R映射即將領(lǐng)域模型類和數(shù)據(jù)庫的表進行映射,通過程序操作對象而實現(xiàn)表數(shù)據(jù)操作的能力,讓數(shù)據(jù)訪問操作無須關(guān)注數(shù)據(jù)庫相關(guān)的技術(shù)2022-08-08
SpringBoot整合PowerJob實現(xiàn)定時任務(wù)調(diào)度
最近項目需要使用定時任務(wù),而使用了PowerJob做任務(wù)調(diào)度模塊,感覺這個框架真香,今天我們就來深入了解一下新一代的定時任務(wù)框架——PowerJob,需要的朋友可以參考下2024-03-03

