温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Netty NIO的简单介绍

发布时间:2021-06-26 10:04:09 来源:亿速云 阅读:194 作者:chen 栏目:大数据

这篇文章主要介绍“Netty NIO的简单介绍”,在日常操作中,相信很多人在Netty NIO的简单介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Netty NIO的简单介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1. 传统IO(BIO)存在的问题

同步阻塞

    也就是传统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,操作完毕的通知,这可以使进程在数据读写时也不阻塞。

2. NIO(AIO)

异步非阻塞

    为了改善传统IO的问题,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的类,可以构建多路复用的同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,读写操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作,并发性能再次提升。针对

NIO核心实现类

    Java中为NIO提供三个核心实现类,主要是缓冲区(Buffer)、通道(Channel)、选择器(Selector)。

1. 通道(Channel)

    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

Netty NIO的简单介绍

    3. Channel有三个特点:

  • Channel是可读可写的,但是一个Channel要么只能写要么只能读

  • Channel可以异步的读和写

  • 数据总是从Channel中读到Buffer,或者从Buffer中写到Channel

2. 缓冲区(Buffer)

    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

3. 选择器(Selector)

    1. 传统IO因为一个线程对应一个IO的局限导致其在高并发下的性能浪费,而NIO中则因为Selector的存在实现了允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

Netty NIO的简单介绍

到此,关于“Netty NIO的简单介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI