这篇文章主要介绍“Netty NIO的简单介绍”,在日常操作中,相信很多人在Netty NIO的简单介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Netty NIO的简单介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
创新互联公司主营伊通网站建设的网络公司,主营网站建设方案,成都app软件开发公司,伊通h5微信小程序开发搭建,伊通网站营销推广欢迎伊通等地区企业咨询
也就是传统IO(也就是InputStream、OutputStream等Java中IO包下的类以及 java.net下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。)在进行读写操作(调用read/write方法)时会停止当前线程,使得当前线程进入阻塞状态,直到读写操作结束后,线程才能继续执行。
传统IO的同步阻塞问题导致了其在性能上的极大缺陷,因为每一个线程在同一时刻只能管理(运行)一个IO流,尤其是对于网络应用程序来说,如果采用传统IO方式,那么只能一个线程管理持有一个IO流,这对于系统来说并发情况下的性能瓶颈就太大了,代码如下所示
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 传统socket服务端 * */ public class ioServer { @SuppressWarnings("resource") public static void main(String[] args) throws Exception { ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); //创建socket服务,监听10101端口 ServerSocket server=new ServerSocket(10101); System.out.println("服务器启动!"); while(true){ //获取一个套接字(阻塞) final Socket socket = server.accept(); System.out.println("来个一个新客户端!"); newCachedThreadPool.execute(new Runnable() { @Override public void run() { //业务处理 handler(socket); } }); } } /** * 读取数据 * @param socket * @throws Exception */ public static void handler(Socket socket){ try { byte[] bytes = new byte[1024]; InputStream inputStream = socket.getInputStream(); while(true){ //读取数据(阻塞) int read = inputStream.read(bytes); if(read != -1){ System.out.println(new String(bytes, 0, read)); }else{ break; } } } catch (Exception e) { e.printStackTrace(); }finally{ try { System.out.println("socket关闭"); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
如果使用传统IO方式,那么就必须为每一个连接到服务端的客户端建立一个线程来处理IO,并发量低的时候还好,可是一旦并发量极高,造成创建大量线程,就会导致非常频繁的进行线程间切换,这对系统性能消耗极大,而且线程切换是无用的消耗。
同步和阻塞是有区别的,它们的修饰对象是不同的。
阻塞和非阻塞是指进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪。
同步和异步是指访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞,异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。
为了改善传统IO的问题,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的类,可以构建多路复用的、同步非阻塞IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,读写操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作,并发性能再次提升。针对
Java中为NIO提供三个核心实现类,主要是缓冲区(Buffer)、通道(Channel)、选择器(Selector)。
1. 通道(Channel):原本在传统IO中是通过流来进行读写操作,但是在NIO中是采用Channel来进行读写操作,Channel替代了传统IO中的流。
2. Java中提供了Channel的几种具体实现类,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
FileChannel:文件IO
DatagramChannel:UDP网络IO
SocketChannel:TCP客户端网络IO
ServerSocketChannel:TCP服务端网络IO
3. Channel有三个特点:
Channel是可读可写的,但是一个Channel要么只能写要么只能读
Channel可以异步的读和写
数据总是从Channel中读到Buffer,或者从Buffer中写到Channel
1. Channel负责读写数据,而缓冲区Buffer则负责临时保存Channel读写的数据,也就是缓存数据,所有的数据都会经过Buffer写入到Channel或者从Channel中读取存储到Buffer。JavaNIO中为Buffer提供了所有基本数据类型的实现类,覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。还有另外一个MappedByteBuffer。
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
1. 传统IO因为一个线程对应一个IO的局限导致其在高并发下的性能浪费,而NIO中则因为Selector的存在实现了允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
到此,关于“Netty NIO的简单介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!