java nio 异步操作 (一)

简介: 先来看些nio基础的类库关系图 用pd大致画了下 相关的图片 上面是一些理论的关系图 下面是一些测试代码  相关的代码 都加了必要的注释 文件通道  FileChannel package test;import java.io.IOException;import java.io.RandomAccessFile;import

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





相关的图片




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

文件通道  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

服务端

  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. }  


客户端

  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

  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

  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

  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. }  


目录
相关文章
|
1月前
|
前端开发 JavaScript Java
使用Ajax进行异步交互:提升Java Web应用的用户体验
【4月更文挑战第3天】Ajax技术在Web开发中提升UX,通过与服务器异步交互实现页面局部更新,无需完整刷新。核心组件包括XMLHttpRequest、JavaScript、HTML/CSS及服务器端脚本。在Java Web应用中,可使用原生JavaScript或框架如jQuery、AngularJS实现Ajax请求。Ajax减少页面刷新,实现实时数据更新,即时表单验证和动态UI,显著改善用户体验,是现代Web开发不可或缺的一部分。
|
2月前
|
存储 Java 数据处理
|
2月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
2月前
|
存储 安全 Java
【深度挖掘Java并发编程底层源码】「底层技术原理体系」带你零基础认识和分析学习相关的异步任务提交机制FutureTask的底层原理
【深度挖掘Java并发编程底层源码】「底层技术原理体系」带你零基础认识和分析学习相关的异步任务提交机制FutureTask的底层原理
16 0
|
11天前
|
安全 Java
【亮剑】Java中的`Future`接口代表异步计算结果,常与`ExecutorService`配合启动任务并获取结果
【4月更文挑战第30天】Java中的`Future`接口代表异步计算结果,常与`ExecutorService`配合启动任务并获取结果。`Future`接口提供`isDone()`、`get()`、`get(timeout, unit)`和`cancel(mayInterruptIfRunning)`等方法。`FutureTask`是`Future`的实现类,可作为`Runnable`执行并返回结果。
|
14天前
|
Java 开发者 UED
Java 异步和事件驱动编程:探索响应式模式
【4月更文挑战第27天】在现代软件开发中,异步和事件驱动编程是提高应用性能和响应性的关键策略。Java 提供了多种机制来支持这些编程模式,使开发者能够构建高效、可扩展的应用程序。
29 4
|
16天前
|
存储 消息中间件 Java
Java多线程实战-异步操作日志记录解决方案(AOP+注解+多线程)
Java多线程实战-异步操作日志记录解决方案(AOP+注解+多线程)
|
17天前
|
缓存 Java API
Java NIO和IO之间的区别
NIO(New IO),这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
16 1
|
17天前
|
监控 安全 Java
一文讲明白Java中线程与进程、并发与并行、同步与异步
一文讲明白Java中线程与进程、并发与并行、同步与异步
8 1
|
22天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。