标签:成本 local key fileread flush 网络操作 状态 OLE 其他
java.io
包.基于流模型实现,使用同步,阻塞方式.即:读输入流或写输出流时,在读或写动作完成之前,读(写)线程一直阻塞.性能差.java.nio
包.可以构建多路复用,同步非阻塞的IO操作.InputStream
,OutputStream
:基于字节操作的IO.Writer
,Reader
:基于字符操作的IO.File
:基于磁盘操作的IO.Socket
:基于网络操作的IO.InputStream
的使用InputStream inputStream = new FileInputStream("src\\IOBIONIOAIO.md");
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
String str = new String(bytes);
inputStream.close();
System.out.println(str);
OutputStream
的使用OutputStream outputStream = null;
outputStream = new FileOutputStream("src\\IOBIONIOAIO.md",true);
outputStream.write("\nOutputStream测试".getBytes("utf-8"));
outputStream.close();
Writer
的使用Writer writer = new FileWriter("src\\IOBIONIOAIO.md",true);
writer.append("\n使用Writer向文件写入数据");
writer.close();
Reader
的使用Reader reader = new FileReader("src\\IOBIONIOAIO.md");
BufferedReader br = new BufferedReader(reader);
StringBuffer sb = new StringBuffer();
String str = null;
while ((str = br.readLine()) != null){
sb.append(str+"\n");
}
br.close();
reader.close();
System.out.println(sb.toString());
调用结果返回之前,当前线程会被挂起.调用线程只有在得到结果之后才返回.
在没有得到结果之前,不会阻塞当前线程.
线程可以在结果返回之前完成其他任务,提高了CPU的利用率.
问题:系统的线程切换增加,需要权衡增加的CPU使用时间和线程切换的成本.
组合方式 | 性能 |
---|---|
同步阻塞 | I/O性能差,CPU大部分在空闲状态 |
同步非阻塞 | 提升I/O性能,增加CPU消耗 |
异步阻塞 | 对I/O能够提升效率 |
异步非阻塞 | 集群之间的消息同步机制 |
// 使用FileWriter向文件写入数据
public void fileWriterTest() throws IOException {
FileWriter fw = new FileWriter("src\\IOBIONIOAIO.md",true);
fw.write("\n来自FileWriter写入的内容");
fw.close();
}
// 使用FileReader读取文件的内容
public void fileReaderTest() throws IOException {
FileReader fr = new FileReader("src\\IOBIONIOAIO.md");
BufferedReader br = new BufferedReader(fr);
StringBuffer sb = new StringBuffer();
String str;
while ((str = br.readLine())!=null){
sb.append(str+"\n");
}
br.close();
fr.close();
System.out.println(sb.toString());
}
使用java.nio
包中的Files
实现对文件的读写:
public void filesWrite() throws IOException {
Files.write(Paths.get("src\\IOBIONIOAIO.md"),"\n使用Files向文件写入数据".getBytes(), StandardOpenOption.APPEND);
}
public void filesRead() throws IOException {
byte[] bytes = Files.readAllBytes(Paths.get("src\\IOBIONIOAIO.md"));
System.out.println(new String(bytes).toString());
}
服务器只给客户端发消息.
客户端将接收到的消息打印.
/**
* 服务器端:
* 调用accept()阻塞线程等待客户端连接.
* 客户端连接后将数据传输过去
*/
public void servers(){
Thread thread = new Thread(() -> {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
try (PrintWriter printWriter = new PrintWriter(socket.getOutputStream())) {
printWriter.println("来自于服务器端的消息");
printWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
thread.start();
}
/**
* 客户端:
* 打开指定的socket端口,
* 使用BufferedReader读取端口传来的数据
*/
public void client(){
try (Socket socket = new Socket(InetAddress.getLocalHost(),port)){
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
br.lines().forEach(s-> System.out.println(s));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
示意图:
public void servers(){
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(4, 4, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
threadPool.execute(()->{
try (Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()){
serverSocketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(),port));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true){
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
try(SocketChannel channel = ((ServerSocketChannel)key.channel()).accept()){
channel.write(Charset.defaultCharset().encode("来自服务器通过NIO写入数据"));
}
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
public void client(){
try (Socket cSocket = new Socket(InetAddress.getLocalHost(),port)){
BufferedReader br = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
br.lines().forEach(s-> System.out.println(s));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
流程:
Selector.open()
建立一个Selector
,充当调度员.ServerSocketChannel
,并向Selector
注册,通过指定的SelectionKey.OP_ACCEPT
告诉调度员,关注的是新的连接请求.Selector
阻塞在select
操作,当有Channel
发生接入请求时,就会被唤醒.示意图:
参考:
标签:成本 local key fileread flush 网络操作 状态 OLE 其他
原文地址:https://www.cnblogs.com/truestoriesavici01/p/13217272.html