慎用bufferedWriter的readLine()方法
为什么要慎用呢?
BufferReader的read方法和readLine方法在任何情况下都是阻塞的。readLine方法每次读一行,相对于一个字符/字节地读取、转换、返回来说,它有一个缓冲区,读满缓冲区才返回;一般情况下,都建议使用它们把其它Reader/InputStream包起来,使得读取数据更高效;对于文件来说,经常遇到一行一行的,特别符合情景。 如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到”/r”、”/n”、”/r/n”才会返回,否则一直阻塞。
说来也是惭愧,这个方法用了无数次,却从未注意过这个方法是阻塞的。今天用socket写了聊天小demo,问题出现了,程序走到readLine()这个地方,一直阻塞着不往下走,结果就发现了这个隐藏很久的坑。
解决办法也比较简单粗暴,就是在传输的字符串后面加上换行符。t和曾经做过一个项目现象比较类似,服务端是netty写的,用来接受不同厂商通过网络设备发送来的消息,在接入的过程中很多厂商的设备的消息发送后都没有返回任何消息,后来在分析中发现,由于接入协议中,要求每隔五分钟各个设备要向服务端发送一条消息,消息的格式是字符串,很多厂商在连接后没有关闭连接,消息与消息之间也没有任何标识一条消息结束的标识符号,出现了粘包。解决方法也差不多,1、传输完成后,必须关闭连接2、每条消息结尾加上换行符’\n‘;
下面贴上代码,有兴趣可以关注一下我,一起讨论下:
NetServer.java:
package com.sq.gaox.io.demo2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Auther: Administrator
* @Date: 2019/1/11 14:45
* @Description:
*/
public class NetServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket=new ServerSocket(7070);
System.out.println(“server is running”);
while (true){
Socket socket= serverSocket.accept();
new Thread(new DoSomeThing(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
DoSomeThing.java:
package com.sq.gaox.io.demo2;
import java.io.*;
import java.net.Socket;
/**
* @Auther: Administrator
* @Date: 2019/1/11 14:47
* @Description:
*/
public class DoSomeThing implements Runnable {
private Socket socket;
public DoSomeThing(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
System.out.println(“连接成功,”+ socket.getInetAddress()+”,当前线程:”+Thread.currentThread().getName());
BufferedReader bufferedReader=null;
// PrintWriter printWriter=null;
BufferedWriter bufferedWriter=null;
try {
bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
// printWriter=new PrintWriter(socket.getOutputStream());
bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String receiveMsg=bufferedReader.readLine();
System.out.println(“服务端收到消息:”+receiveMsg.toString());
// printWriter.println(“hello , this is server”);
// printWriter.flush();
bufferedWriter.write(“this is server by bufferedwriter\r”);
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// if (printWriter != null) {
// printWriter.close();
// }
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
NetClient.java:
package com.sq.gaox.io.demo2;
import java.io.*;
import java.net.Socket;
/**
* @Auther: Administrator
* @Date: 2019/1/11 14:51
* @Description:
*/
public class NetClient {
public static void main(String[] args) {
Socket socket = null;
// PrintWriter printWriter = null;
BufferedWriter bufferedWriter=null;
BufferedReader bufferedReader = null;
try {
socket = new Socket(“localhost”, 7070);
// printWriter = new PrintWriter(socket.getOutputStream());
bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// printWriter.println(“hello , this is client”);
// printWriter.flush();
bufferedWriter.write(“hello , this client by bufferwriter\r”);
bufferedWriter.flush();
String receiveMsg=bufferedReader.readLine();
System.out.println(“服务端收到消息:” + receiveMsg.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// if (printWriter != null) {
// printWriter.close();
// }
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
还没有评论,来说两句吧...