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


目录
打赏
0
0
0
0
138
分享
相关文章
|
22天前
|
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
84 17
|
5月前
|
探索Java新境界!异步+事件驱动,打造响应式编程热潮,未来已来!
【8月更文挑战第30天】在现代软件开发中,系统响应性和可扩展性至关重要。Java作为主流编程语言,提供了多种机制如Future、CompletableFuture及事件驱动编程,有效提升应用性能。本文探讨Java异步编程模型与事件驱动编程,并介绍响应式模式,助您构建高效、灵活的应用程序。
74 3
|
1月前
|
探索Java NIO:究竟在哪些领域能大显身手?揭秘原理、应用场景与官方示例代码
Java NIO(New IO)自Java SE 1.4引入,提供比传统IO更高效、灵活的操作,支持非阻塞IO和选择器特性,适用于高并发、高吞吐量场景。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector),能实现多路复用和异步操作。其应用场景涵盖网络通信、文件操作、进程间通信及数据库操作等。NIO的优势在于提高并发性和性能,简化编程;但学习成本较高,且与传统IO存在不兼容性。尽管如此,NIO在构建高性能框架如Netty、Mina和Jetty中仍广泛应用。
47 3
|
1月前
|
Java的NIO体系
通过本文的介绍,希望您能够深入理解Java NIO体系的核心组件、工作原理及其在高性能应用中的实际应用,并能够在实际开发中灵活运用这些知识,构建高效的Java应用程序。
51 5
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
Java CompletableFuture 异步超时实现探索
本文探讨了在JDK 8中`CompletableFuture`缺乏超时中断任务能力的问题,提出了一种异步超时实现方案,通过自定义工具类模拟JDK 9中`orTimeout`方法的功能,解决了任务超时无法精确控制的问题,适用于多线程并行执行优化场景。
Java NIO 开发
本文介绍了Java NIO(New IO)及其主要组件,包括Channel、Buffer和Selector,并对比了NIO与传统IO的优势。文章详细讲解了FileChannel、SocketChannel、ServerSocketChannel、DatagramChannel及Pipe.SinkChannel和Pipe.SourceChannel等Channel实现类,并提供了示例代码。通过这些示例,读者可以了解如何使用不同类型的通道进行数据读写操作。
Java NIO 开发
|
3月前
|
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
54 2
JAVA并发编程系列(13)Future、FutureTask异步小王子
本文详细解析了Future及其相关类FutureTask的工作原理与应用场景。首先介绍了Future的基本概念和接口方法,强调其异步计算特性。接着通过FutureTask实现了一个模拟外卖订单处理的示例,展示了如何并发查询外卖信息并汇总结果。最后深入分析了FutureTask的源码,包括其内部状态转换机制及关键方法的实现原理。通过本文,读者可以全面理解Future在并发编程中的作用及其实现细节。
Ajax进行异步交互:提升Java Web应用的用户体验
Ajax 技术允许在不重载整个页面的情况下与服务器异步交换数据,通过局部更新页面内容,极大提升了 Java Web 应用的响应速度和用户体验。本文介绍 Ajax 的基本原理及其实现方式,包括使用 XMLHttpRequest 对象发送请求、处理响应数据,并在 Java Web 应用中集成 Ajax。此外,还探讨了 Ajax 如何通过减少页面刷新、实时数据更新等功能改善用户体验。
91 3

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等