Hi everybody, I'm
方圆
table of Contents
1 Overview
1.1 Translation translation? What is NIO?
NIO: I think the translation is Non-Blocking
more straightforward. Compared with BIO, there is also a comparison. It is best to call him non-blocking IO.
- It has the following differences from BIO
- Channel Yes
双向
, it can read and write. Compared with Stream, it does not distinguish between input stream and output stream, and Channel can complete non-blocking read and write, as well as block read and write
1.2 Introduction to Buffer
- Channel reading and writing are inseparable from Buffer. Buffer is actually an area in the memory for reading and writing.
1.2.1 Write mode
- Three of the pointers we need to understand
position
are the current pointer position, which islimit
used in the read mode. It is used to mark the maximum readable range, whichcapacity
is the maximum writable range threshold.
When we write data and write four grids, we execute the flip()
method, and it can be changed to the 读模式
limit pointer directly changed to the limit position of the data we just wrote, and the position pointer returns to the initial position, so that we can read the data out
1.2.2 Two switching from read mode to write mode
- When we have read all the data, switch to the write mode and
call theclear()
method. It will return the position pointer to the initial position and limit back to the farthest end, so that the data can be restarted. Although clear means clear, in fact it Just move the position of the pointer, and does not clear the data, but will overwrite the original position
- Read only part of the data, I think part of the reservation will be unread, and now I have to start to write mode of operation, so you can perform the
compact()
method
This method将没有读到的数据保存到初始位置
, whichposition指针的位置将会移动到这些数据的后面位置
, after reading the data never started writing data
after When reading the data again, we can read out the data that was not read last time
1.3 Introduction to Channel
Data exchange between channels all need to rely on Buffer
1.3.1 Several important channels
- FileChannel: used for file transfer
- ServerSocketChannel and SocketChannel: transmission for network programming
2. File copy combat
- A byte-by-byte copy is really slow.
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
interface FileCopyRunner{
void copyFile(File source,File target);
}
public class FileCopyDemo {
private static void close(Closeable closeable){
if(closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//不使用任何缓冲的留的拷贝
private static FileCopyRunner noBufferStreamCopy = new FileCopyRunner() {
@Override
public void copyFile(File source, File target) {
InputStream fin = null;
OutputStream fout = null;
try {
fin = new FileInputStream(source);
fout = new FileOutputStream(target);
int result;
while((result = fin.read()) != - 1){
fout.write(result);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
}
};
//使用缓冲区的流的拷贝
private static FileCopyRunner bufferStreamCopy = new FileCopyRunner() {
@Override
public void copyFile(File source, File target) {
InputStream fin = null;
OutputStream fout = null;
try {
fin = new FileInputStream(source);
fout = new FileOutputStream(target);
//创建缓冲区
byte[] buffer = new byte[1024];
int result;
while((result = fin.read(buffer)) != -1){
//result这里表示从中读出来的具体字节数
//虽然缓冲区中能缓存1024,但是我们读取的时候不一定就有这么多字节
//所以我们使用result做下面的参数
fout.write(buffer,0,result);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
}
};
//使用带有缓冲区的channel复制 nio
private static FileCopyRunner nioBufferCopy = new FileCopyRunner() {
@Override
public void copyFile(File source, File target) {
FileChannel fin = null;
FileChannel fout = null;
try {
fin = new FileInputStream(source).getChannel();
fout = new FileOutputStream(target).getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while(fin.read(byteBuffer) != -1){
byteBuffer.flip();//转变为读模式
while (byteBuffer.hasRemaining()){
fout.write(byteBuffer);
}
byteBuffer.clear();//转变为写模式
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
}
};
//使用没有缓冲区的channel复制文件
private static FileCopyRunner nioTransferCopy = ((source, target) -> {
FileChannel fin = null;
FileChannel fout = null;
try {
fin = new FileInputStream(source).getChannel();
fout = new FileOutputStream(target).getChannel();
long transferred = 0L;
long size = fin.size();
while(transferred != size){
//如果拷贝的大小没有达到源文件的大小就要一直拷贝
transferred += fin.transferTo(0,size,fout);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
});
public static void main(String[] args) {
File source = new File("J:\\StudySpace\\Java秒杀系统方案优化-高性能高并发实战\\project.zip");
File target = new File("J:\\StudySpace\\Java秒杀系统方案优化-高性能高并发实战\\p1.zip");
File target2 = new File("J:\\StudySpace\\Java秒杀系统方案优化-高性能高并发实战\\p2.zip");
File target3 = new File("J:\\StudySpace\\Java秒杀系统方案优化-高性能高并发实战\\p3.zip");
File target4 = new File("J:\\StudySpace\\Java秒杀系统方案优化-高性能高并发实战\\p4.zip");
new Thread(() -> noBufferStreamCopy.copyFile(source,target)).start();
new Thread(() -> bufferStreamCopy.copyFile(source,target2)).start();
new Thread(() -> nioBufferCopy.copyFile(source,target3)).start();
new Thread(() -> nioTransferCopy.copyFile(source,target4)).start();
}
}
3. Overview of Selector
- Channel needs to be registered on Selector
- At the same time of registration, you must tell the Selector the monitoring status
- The corresponding states of Channel are::
CONNECT
socketChannel has established a connection with the server;: serverSocketChannel has established a connectionACCEPT
with the client;:READ
readable state ;:WRITE
writable state
- After registration is complete in the Channel Selector, will return a SelectKey objects, which has several important ways:
interestOps
: View the status of the registered Channel bindings;readyOps
: to see which is the operational state;channel
: Return channel objects;selector
: Return target selector ;attachment
: Attach other objects - Call the select method of the Selector to return the number of events it monitors, which can respond to multiple events at the same time. However, it is a blocking call. When there is no monitoring event that can be used to respond to the request, it will be blocked and will not return until there is an available channel that can respond to the request.
Come on!