java nio 异步操作 (一)

时间:2022-09-05 14:50:51

先来看些nio基础的类库关系图 用pd大致画了下

java nio 异步操作 (一)


java nio 异步操作 (一)




相关的图片

java nio 异步操作 (一)


java nio 异步操作 (一)



上面是一些理论的关系图 下面是一些测试代码  相关的代码 都加了必要的注释

文件通道  FileChannel

package test;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;


/**
* 文件通道测试类
* FileChannel文件通道只能使用阻塞模式
* AsynchronousFileChannel 异步 可以使用异步模式
* A FileChannel cannot be set into non-blocking mode. It always runs in blocking mode
* @author u1
*
*/
public class BasicFileChannel {

RandomAccessFile randomAccessFile;
FileChannel channel;
ByteBuffer buffer;
AsynchronousFileChannel fileChannel;

@Before
public void before() throws IOException{
randomAccessFile=new RandomAccessFile(ClassLoader.getSystemResource("selector.txt").getFile(), "rw");
channel=randomAccessFile.getChannel();
//强制刷新
channel.force(true);
buffer=ByteBuffer.allocate(102400);
String aaa=buffer.toString();
System.out.println(aaa);
}

@After
public void after() throws IOException{
randomAccessFile.close();
channel.close();
}

/**
* //1、读取数据Buffer
//2、转换模式
//3、读取Buffer
//4、清除Buffers
* @throws IOException
*/
@Test
public void readTest() throws IOException{
System.out.println(read());
}

private String read() throws IOException {
StringBuilder builder=new StringBuilder();
int readByte=channel.read(buffer);
while(readByte!=-1){
//1、读取数据Buffer
//2、转换模式
buffer.flip();
//3、读取Buffer
byte[] datas=new byte[buffer.limit()];
buffer.get(datas);
//System.out.println(new String(datas));
builder.append(new String(datas));
//4、清除Buffer
buffer.clear();
readByte=channel.read(buffer);
}
String aa=builder.toString();
return aa;
}

/**
* 将读出的文件内容回写到文件中
* 从文件的开始地方写入
* @throws IOException
*/
@Test
public void writeTest() {
try {

//获取原有字符串
String originString=read();
//写入到buffer
buffer.put(originString.getBytes());
//转换模式
buffer.flip();
//将buffer中的数据写入到文件中
channel.position(0);
System.out.println("size:"+channel.size()+"\t"+"position:"+channel.position());
@SuppressWarnings("resource")
RandomAccessFile randomAccessFile2=new RandomAccessFile("/home/lhy/data/aaaa.txt", "rw");

FileChannel channel2=randomAccessFile2.getChannel();
while(buffer.hasRemaining())
{
channel2.write(buffer);
System.out.println("0000000000000000");
}

} catch (Exception e) {
e.printStackTrace();
}
System.out.println("11111111111111111111111");

}

//@Test
public void writeAsyncTest() throws IOException, URISyntaxException{
//获取原有字符串
String originString=read();
originString+=System.currentTimeMillis();
//写入到buffer
buffer.put(originString.getBytes());
//转换模式
buffer.flip();
//Path file=Paths.get(ClassLoader.getSystemResource("selector1.txt").toURI());
Path file=Paths.get("/home/lhy/data/aaaa.txt");
fileChannel=AsynchronousFileChannel.open(file, StandardOpenOption.WRITE);
fileChannel.force(true);
//fileChannel.write(buffer, 10);
fileChannel.write(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {

@Override
public void completed(Integer result, ByteBuffer attachment) {
// TODO Auto-generated method stub
System.out.println("写完文件后操作,不阻塞,已经写了"+result);
close();
}

@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// TODO Auto-generated method stub
System.out.println("写失败");
exc.printStackTrace();
}
});

System.out.println("000000000000000000000000000000000000000000000000000000");
}
public void close(){
try {
fileChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}




多路复用器  Selector

服务端

[java] view plain copy
  1. package com.undergrowth;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.net.InetSocketAddress;  
  7. import java.net.Socket;  
  8. import java.nio.channels.SelectionKey;  
  9. import java.nio.channels.Selector;  
  10. import java.nio.channels.ServerSocketChannel;  
  11. import java.util.Iterator;  
  12. import java.util.Set;  
  13.   
  14. import org.junit.After;  
  15. import org.junit.Before;  
  16. import org.junit.Test;  
  17.   
  18. /** 
  19.  * 测试多路复用器 Selector 
  20.  * @author u1 
  21.  * 
  22.  */  
  23. public class BasicSelector {  
  24.       
  25.     //多路复用器  检测7777和8888端口  
  26.     private Selector selector;  
  27.     private ServerSocketChannel channel7777,channel8888;  
  28.       
  29.     @Before  
  30.     public void before() throws IOException{  
  31.         selector=Selector.open();  
  32.         //打开7777端口服务通道  
  33.         channel7777=ServerSocketChannel.open();  
  34.         //绑定7777端口的服务监听  
  35.         channel7777.socket().bind(new InetSocketAddress(7777));  
  36.         //配置为非阻塞模式  
  37.         channel7777.configureBlocking(false);  
  38.         //将通道注册到多路复用器上  
  39.         channel7777.register(selector,  SelectionKey.OP_ACCEPT);  
  40.         //打开8888端口服务通道  
  41.         channel8888=ServerSocketChannel.open();  
  42.         //绑定8888端口的服务监听  
  43.         channel8888.socket().bind(new InetSocketAddress(9999));  
  44.         //配置为非阻塞模式  
  45.         channel8888.configureBlocking(false);  
  46.         //关注读操作  
  47.         channel8888.register(selector, SelectionKey.OP_ACCEPT);  
  48.     }  
  49.       
  50.     /** 
  51.      * 关闭资源 
  52.      * @throws IOException 
  53.      */  
  54.     @After  
  55.     public void after() throws IOException{  
  56.         selector.close();  
  57.         channel7777.close();  
  58.         channel8888.close();  
  59.     }  
  60.       
  61.     @Test  
  62.     public void select() throws IOException{  
  63.         //控制循环  
  64.         BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));  
  65.         while(true){  
  66.             System.out.println("是否还要进行");  
  67.             String isGoString=reader.readLine();  
  68.             if("N".equalsIgnoreCase(isGoString)) break;  
  69.             System.out.println("等待事件源发生");  
  70.             //等待注册的事件源发生  
  71.             int readyChannel=selector.select();  
  72.             if(readyChannel==0continue;  
  73.             System.out.println("有"+readyChannel+"个准备好了");  
  74.             //获取准备好的通道  
  75.             Set<SelectionKey> selectionKeys=selector.selectedKeys();  
  76.             Iterator<SelectionKey> selectKeyIterator=selectionKeys.iterator();  
  77.             while (selectKeyIterator.hasNext()) {  
  78.                 SelectionKey selectionKey = (SelectionKey) selectKeyIterator  
  79.                         .next();  
  80.                 //遍历注册中准备好的事件源  
  81.                 interestSet(selectionKey.interestOps());  
  82.                 if(selectionKey.isAcceptable()){  
  83.                     //当客户端进行连接时  获取socket  会写信息  
  84.                     ServerSocketChannel serverSocketChannel=(ServerSocketChannel) selectionKey.channel();  
  85.                     System.out.println(serverSocketChannel.socket().getLocalPort()+"端口\t"+"感兴趣的操作:"+serverSocketChannel.validOps());  
  86.                     Socket socket=serverSocketChannel.socket().accept();  
  87.                     socket.getOutputStream().write("从selector中返回给客户端".getBytes());  
  88.                     socket.getOutputStream().flush();  
  89.                     socket.close();  
  90.                 }  
  91.                 //移除已经处理的事件源  
  92.                 selectKeyIterator.remove();  
  93.             }  
  94.         }  
  95.           
  96.           
  97.     }  
  98.   
  99.     /** 
  100.      * 遍历注册中准备好的事件源 
  101.      * @param interestOps 
  102.      */  
  103.     private void interestSet(int interestSet) {  
  104.         // TODO Auto-generated method stub  
  105.         if((interestSet&SelectionKey.OP_ACCEPT)!=0) System.out.println("注册的可接受");  
  106.         if((interestSet&SelectionKey.OP_CONNECT)!=0) System.out.println("注册的可连接");  
  107.         if((interestSet&SelectionKey.OP_READ)!=0) System.out.println("注册的可读");  
  108.         if((interestSet&SelectionKey.OP_WRITE)!=0) System.out.println("注册的可写");  
  109.     }  
  110.       
  111.       
  112. }  


客户端

[java] view plain copy java nio 异步操作 (一)java nio 异步操作 (一)
  1. package com.undergrowth;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.net.InetSocketAddress;  
  7. import java.net.Socket;  
  8.   
  9.   
  10. /** 
  11.  * 连接服务ServerSocket 
  12.  * @author u1 
  13.  * 
  14.  */  
  15. public class BasicSocketChannel {  
  16.   
  17.     /** 
  18.      * @param args 
  19.      * @throws IOException  
  20.      */  
  21.     public static void main(String[] args) throws IOException {  
  22.         // TODO Auto-generated method stub  
  23.           
  24.         //用于客户端的Socket连接 测试  
  25.         Socket socket=new Socket();  
  26.         socket.connect(new InetSocketAddress(7777));  
  27.         BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));   
  28.         System.out.println("读取的字符串为:"+reader.readLine());  
  29.           
  30.     }  
  31.   
  32. }  


路径   Path与Paths

[java] view plain copy java nio 异步操作 (一)java nio 异步操作 (一)
  1. package com.undergrowth;  
  2.   
  3. import java.nio.file.Path;  
  4. import java.nio.file.Paths;  
  5.   
  6. import org.junit.Test;  
  7.   
  8. /** 
  9.  * A Java Path instance represents a path in the file system. A path can point 
  10.  * to either a file or a directory. A path can be absolute or relative. An 
  11.  * absolute path contains the full path from the root of the file system down to 
  12.  * the file or directory it points to. A relative path contains the path to the 
  13.  * file or directory relative to some other path. 
  14.  *  
  15.  * @author u1 
  16.  *  
  17.  */  
  18. public class BasicPath {  
  19.   
  20.     /** 
  21.      * 测试绝对路径 
  22.      */  
  23.     @Test  
  24.     public void testAbsolute() {  
  25.         Path path=Paths.get("E:\\book""JAVA_API_1.7中文.chm");  
  26.         System.out.println(path.toString());  
  27.     }  
  28.   
  29.     /** 
  30.      * 测试相对路径 
  31.      * .---->当前路径 
  32.      * ..---->父路径 
  33.      */  
  34.     @Test  
  35.     public void testRelative(){  
  36.         Path path=Paths.get(".");  
  37.         System.out.println(path.toAbsolutePath());  
  38.         path=Paths.get("..");  
  39.         System.out.println(path.toAbsolutePath());  
  40.     }  
  41.       
  42.     /** 
  43.      * 格式化Path路径  
  44.      * 去除.和.. 
  45.      */  
  46.     @Test  
  47.     public void testNormalize(){  
  48.         Path path=Paths.get("E:\\book\\weblogic\\.\\51CTO下载-Oracle WebLogic Server开发权威指南.part1.rar");  
  49.         System.out.println(path.toAbsolutePath());  
  50.         System.out.println(path.normalize().toAbsolutePath());  
  51.         path=Paths.get("E:\\book\\..\\");  
  52.         System.out.println(path.toAbsolutePath());  
  53.         System.out.println(path.normalize().toAbsolutePath());  
  54.     }  
  55.       
  56. }  



管道  Pipe

[java] view plain copy java nio 异步操作 (一)java nio 异步操作 (一)
  1. package com.undergrowth;  
  2.   
  3. import java.io.IOException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.Pipe;  
  6.   
  7. import org.junit.Before;  
  8. import org.junit.Test;  
  9.   
  10. /** 
  11.  * 管道操作 
  12.  *  
  13.  * A Java NIO Pipe is a one-way data connection between two threads. A Pipe has 
  14.  * a source channel and a sink channel. You write data to the sink channel. This 
  15.  * data can then be read from the source channel 
  16.  *  
  17.  * @author u1 
  18.  *  
  19.  */  
  20. public class BasicPipe {  
  21.   
  22.     Pipe pipe;  
  23.     Pipe.SinkChannel writePipe;  
  24.     Pipe.SourceChannel readPipe;  
  25.     ByteBuffer buffer;  
  26.       
  27.     @Before  
  28.     public void before() throws IOException{  
  29.         pipe=Pipe.open();  
  30.         writePipe=pipe.sink();  
  31.         readPipe=pipe.source();  
  32.         buffer=ByteBuffer.allocate(1024);  
  33.     }  
  34.       
  35.     @Test  
  36.     public void testPipe() throws IOException{  
  37.         String string="通过管道进行传输数据";  
  38.         buffer.put(string.getBytes());  
  39.         buffer.flip();  
  40.         //将数据写入接受的通道中  
  41.         while(buffer.hasRemaining()) writePipe.write(buffer);  
  42.         //将数据从读的通道中读出  
  43.         ByteBuffer byteBuffer=ByteBuffer.allocate(1024);  
  44.         StringBuilder builder=new StringBuilder();  
  45.         int readByte=readPipe.read(byteBuffer);  
  46.         byteBuffer.flip();  
  47.         byte[] dst=new byte[byteBuffer.limit()];  
  48.         byteBuffer.get(dst);  
  49.         builder.append(new String(dst));  
  50.         byteBuffer.clear();  
  51.         System.out.println("从读的通道中读出的数据为:"+builder.toString());  
  52.     }  
  53. }  



文件  Files

[java] view plain copy java nio 异步操作 (一)java nio 异步操作 (一)
  1. package com.undergrowth;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import java.io.IOException;  
  6. import java.nio.file.FileVisitResult;  
  7. import java.nio.file.FileVisitor;  
  8. import java.nio.file.Files;  
  9. import java.nio.file.LinkOption;  
  10. import java.nio.file.Path;  
  11. import java.nio.file.Paths;  
  12. import java.nio.file.SimpleFileVisitor;  
  13. import java.nio.file.StandardCopyOption;  
  14. import java.nio.file.attribute.BasicFileAttributes;  
  15.   
  16. import org.junit.Test;  
  17.   
  18. /** 
  19.  * The Java NIO Files class (java.nio.file.Files) provides several methods for 
  20.  * manipulating files in the file system. 
  21.  * 文件操作类 
  22.  *    新建两个文件夹 再将文件复制到两文件夹中 然后进行遍历文件树 遍历完成后 删除文件夹及文件 
  23.  * @author u1 
  24.  *  
  25.  */  
  26. public class BasicFiles {  
  27.   
  28.     @Test  
  29.     public void test() throws IOException {  
  30.         //获取路径  
  31.         Path path=Paths.get(".\\test");  
  32.         //分别创建两个文件夹 在test里面 分别为test1 和  test2  
  33.         createDir(path);  
  34.         //复制文件  
  35.         copyFiles(path);  
  36.         //遍历文件  
  37.         path=Paths.get(".\\test");  
  38.         walkFile(path);  
  39.     }  
  40.   
  41.     /** 
  42.      * 遍历文件目录 
  43.      * @param path 
  44.      * @throws IOException  
  45.      */  
  46.     private void walkFile(Path path) throws IOException {  
  47.         // TODO Auto-generated method stub  
  48.         Files.walkFileTree(path, new SimpleFileVisitor<Path>(){  
  49.   
  50.             @Override  
  51.             public FileVisitResult visitFile(Path file,  
  52.                     BasicFileAttributes attrs) throws IOException {  
  53.                 // TODO Auto-generated method stub  
  54.                 //删除文件  
  55.                 System.out.println("删除"+file.toFile().getAbsolutePath());  
  56.                 Files.delete(file);  
  57.                 return FileVisitResult.CONTINUE;  
  58.             }  
  59.   
  60.             @Override  
  61.             public FileVisitResult postVisitDirectory(Path dir, IOException exc)  
  62.                     throws IOException {  
  63.                 // TODO Auto-generated method stub  
  64.                 //遍历完目录后删除  
  65.                 System.out.println("遍历完目录后删除"+dir.toAbsolutePath());  
  66.                 Files.delete(dir);  
  67.                 return FileVisitResult.CONTINUE;  
  68.             }  
  69.               
  70.         });  
  71.     }  
  72.   
  73.     /** 
  74.      * 复制文件 
  75.      * @param path 
  76.      * @throws IOException  
  77.      */  
  78.     private void copyFiles(Path path) throws IOException {  
  79.         // TODO Auto-generated method stub  
  80.         Path pathSource =Paths.get("..\\git.txt");  
  81.         path=Paths.get(".\\test\\test1\\git.txt");  
  82.         //替换已经存在的文件  
  83.         Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);  
  84.         path=Paths.get(".\\test\\test2\\git.txt");  
  85.         Files.copy(pathSource, path,StandardCopyOption.REPLACE_EXISTING);  
  86.     }  
  87.   
  88.     /** 
  89.      * 创建文件夹 
  90.      * @param path 
  91.      * @throws IOException 
  92.      */  
  93.     private void createDir(Path path) throws IOException {  
  94.         // TODO Auto-generated method stub  
  95.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  96.             Files.createDirectories(path);  
  97.         path=Paths.get(path.toString(), "test1");  
  98.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  99.             Files.createDirectories(path);  
  100.         path=Paths.get(path.toString(), "..\\test2");  
  101.         if(!Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS}))  
  102.             Files.createDirectories(path);  
  103.     }  
  104.   
  105.       
  106. }