Java NIO概述及要点摘录

#普通IO与NIO区别?

IO:按流处理数据,速度慢;普通IO;
NIO:按块处理数据,速度快;通过通道channel和缓冲区buffer作为基础的面向块的IO处理;

#通道channel和缓冲区buffer是什么?
通道和缓冲区是NIO的核心对象;
channel是对原有IO包中流的模拟,到任何目的地的数据都需要通过channel对象;字节
buffer是一个容器对象,发送给一个channel的所有对象都必须首先放到buffer中,同样,从channel中读取的数据都要读到buffer中,是不能直接从channel中读取数据的,只能通过buffer;
buffer是一个数据,常用的是字节数组ByteBuffer,缓冲区还提供了对数据的结构化访问,可以跟踪系统的读写进程;

#通道channel是对旧的IO流的模拟,那么通道与旧的io流的区别在哪里?
channel是双向的,可以同时读写,unix底层操作系统通道也是双向的;
旧的IO流是单向的;

#NIO的文件读写
读取文件步骤:从FileInputStream获取channel,创建Buffer,将数据从channel读到buffer中;
读文件:

FileInputStream fin = new FileInputStream("demo.txt");
FileChannel fc = fin.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);

 

 写文件:

FileOutputStream fout = new FileOutputStream("demo.txt");
FileChannel fc - fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
for(int i=0; i< message.length; i++){
	buffer.put(message[i]);
}
buffer.flip();
fc.write(buffer);

#NIO读写时,我们不需要告诉通道要读多少数据到缓冲区中,每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据及还有多少空间可以容纳更多的数据,JDK中是如何设计和实现这个个机制的?(待深入研究.)

 

#缓冲区内部实现机制
缓冲区的两个重要实现组件:状态变量,访问方法;
每一种java基本类型的缓冲区都是对象类Buffer的子类;buffer有三个似有属性:
private int position = 0;//跟踪了向缓冲区中写入多少数据或者从缓冲区中读取了多少数据;
private int limit;//表明还有多少数据需要取出,或还有多少空间可以放入数据;
private int capacity;//该缓冲区的最大数据容量;
每个基本类型的缓冲区底层实上就是一个该类型的数组;例如ByteBuffer中的final byte[] nb;
从通道读取数据,实际上是将读取的数据放到该数组中,向通道中写入时,是将该数组中的数据写入到通道中;
#如何使用
使用缓冲区将数据从输入通道拷贝到输出通道:

while(true){
	buffer.clear();
	int r = fcin.read(buffer);
	if(r==-1){
		break;
	}
	buffer.flip();
	fcout.write(buffer);
}

 其中:clear(),flip()用于让缓冲区在读写之间切换;

 

#连网与异步IO
nio中的连网与nio中的其它操作无区别,仍然是依赖于通道和缓冲区,使用InputStream和OutputStream获取通道;
异步io调用不会阻塞。它的最大优势:允许同时根据大量的输入和输出执行IO,同步程序常常求助于轮询或者创建许多线程处理大量连接,使用异步IO,可以监听任何数量的通道上的事件,不用轮询,也不用额外的线程;

应用实例:基于非组赛io的服务器端的处理流程,它接收网络连接并向它们回响它们可能发送的数据。

private void execute () throws IOException { // 创建一个新的选择器
	Selector selector = Selector.open();
	// 打开在每个端口上的监听,并向给定的选择器注册此通道接受客户端连接的I/O事件。 
	for (int i = 0; i < ports.length; i++) {
		// 打开服务器套接字通道
		ServerSocketChannel ssc = ServerSocketChannel.open(); // 设置此通道为非阻塞模式
		ssc.configureBlocking(false);
		// 绑定到特定地址
		ServerSocket ss = ssc.socket();
		InetSocketAddress address = new InetSocketAddress(ports[i]); ss.bind(address);
		// 向给定的选择器注册此通道的接受连接事件 
		ssc.register(selector, SelectionKey.OP_ACCEPT); 
		System.out.println("Going to listen on " + ports[i]);
	}
	while (true) {
		// 这个方法会阻塞,直到至少有一个已注册的事件发生。
		// 当一个或者更多的事件发生时,此方法将返回所发生的事件的数量。 int num = selector.select();
		// 迭代所有的选择键,以处理特定的I/O事件。
		Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iter = selectionKeys.iterator();
    	SocketChannel sc;
    	while (iter.hasNext()) {
        	SelectionKey key = iter.next();
		if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) { 
			// 接受服务器套接字撒很能够传入的新的连接,并处理接受连接事件。 
			ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
			sc = ssc.accept();
			// 将新连接的套接字通道设置为非阻塞模式 
			sc.configureBlocking(false);
			// 接受连接后,在此通道上从新注册读取事件,以便接收数据。 
			sc.register(selector, SelectionKey.OP_READ);
			// 删除处理过的选择键
			iter.remove();
	            	System.out.println("Got connection from " + sc);
        	} else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
			// 处理读取事件,读取套接字通道中发来的数据。 
			sc = (SocketChannel) key.channel();
			// 读取数据
			int bytesEchoed = 0; 
			while (true) {
	                    echoBuffer.clear();
	                    int r = sc.read(echoBuffer);
	                    if (r == -1) {
	                        break;
			}
	                echoBuffer.flip();
	                sc.write(echoBuffer);
	                bytesEchoed += r;
	       }
	      System.out.println("Echoed " + bytesEchoed + " from " + sc); // 删除处理过的选择键
	      iter.remove();
	} 
    }
  } 
}

 

 #使用allocate()分配缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);

 其中,allocate()方法分配一个具有指定大小的底层数组,同时包装到一个对象中,例如ByteBuffer;

 

#使用数组转换成缓冲区

byte array[] = new byte[1024];
ByteBuffer buffer = ByteBuffer.wrap(array);

 #缓冲区如何分片

 

实际上就是创建一个子缓冲区,新旧缓冲区的一部分共享数据;

ByteBuffer buffer = ByteBuffer.allocate(10);
for(int i=0; i<buffer.capacity(); i++){
	buffer.put((byte)i):
}
//分片
buffer.position(3);
buffer.limit(7);
ByteBuffer slice = buffer.slice();

 #如何创建只读缓冲区,及作用?

 

调用缓冲区的asReadOnlyBuffer()方法,将缓冲区转化为只读,只读缓冲区可以保护数据,使数据不被修改;

#直接和间接缓冲区
#内存映射文件IO

#将文件的前1024个字节映射到内存

MappedByteBuffer mbf = fc.map(FileChannel.MapModel.READ_WRITE, 0 , 1024);
<pre>
#分散,聚集IO 
读:
 <pre lang="java">
long read(ByeteBuffer[] dst);
long read(ByteBuffer[] dst, in offset, int length);

 

 写:

long write(ByeteBuffer[] dst);
long write(ByteBuffer[] dst, in offset, int length);

 

 

参考:《NIO学习总结.pdf》

C语言-光伏MPPT算法:电导增量法扰动观察法+自动全局搜索Plecs最大功率跟踪算法仿真内容概要:本文档主要介绍了一种基于C语言实现的光伏最大功率点跟踪(MPPT)算法,结合电导增量法与扰动观察法,并引入自动全局搜索策略,利用Plecs仿真工具对算法进行建模与仿真验证。文档重点阐述了两种经典MPPT算法的原理、优缺点及其在不同光照和温度条件下的动态响应特性,同时提出一种改进的复合控制策略以提升系统在复杂环境下的跟踪精度与稳定性。通过仿真结果对比分析,验证了所提方法在快速性和准确性方面的优势,适用于光伏发电系统的高效能量转换控制。; 适合人群:具备一定C语言编程基础和电力电子知识背景,从事光伏系统开发、嵌入式控制或新能源技术研发的工程师及高校研究人员;工作年限1-3年的初级至中级研发人员尤为适合。; 使用场景及目标:①掌握电导增量法与扰动观察法在实际光伏系统中的实现机制与切换逻辑;②学习如何在Plecs中搭建MPPT控制系统仿真模型;③实现自动全局搜索以避免传统算法陷入局部峰值问题,提升复杂工况下的最大功率追踪效率;④为光伏逆变器或太阳能充电控制器的算法开发提供技术参考与实现范例。; 阅读建议:建议读者结合文中提供的C语言算法逻辑与Plecs仿真模型同步学习,重点关注算法判断条件、步长调节策略及仿真参数设置。在理解基本原理的基础上,可通过修改光照强度、温度变化曲线等外部扰动因素,进一步测试算法鲁棒性,并尝试将其移植到实际嵌入式平台进行实验验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值