我正在努力理解SocketChannels和NIO。我知道如何使用常规套接字,以及如何制作一个简单的每个客户端线程服务器(使用常规阻塞套接字)。
所以我的问题是:
A selectable channel for stream-oriented connecting sockets.。那是什么意思?我读过同样的这份文件,但不知怎么的,我没有读到.
发布于 2013-01-09 00:31:15
Socket是一种阻塞输入/输出设备。它使正在使用它的Thread在读取时阻塞,如果底层缓冲区已满,还可能会阻止写入。因此,如果服务器有一堆打开的Socket,则必须创建一组不同的线程。
SocketChannel是一种从套接字中读取数据的非阻塞方式,因此您可以让一个线程同时与一组打开的连接进行通信。这可以通过将一组SocketChannel添加到Selector中,然后在选择器的select()方法上循环,如果套接字已被接受、已接收数据或已关闭,该方法可以通知您。这允许您在一个线程中与多个客户端通信,而不需要多个线程和同步的开销。
Buffer是NIO的另一个特性,它允许您从读写中访问底层数据,以避免将数据复制到新数组中的开销。
发布于 2013-01-09 20:13:51
到目前为止,NIO已经太老了,很少有人记得1.4之前的NIO是什么样子的,为了理解NIO的“原因”,您需要知道这一点。
简而言之,到Java1.3为止,所有I/O都是阻塞类型的。更糟糕的是,没有select()系统调用多路I/O的模拟,因此,用Java实现的服务器别无选择,只能采用“每个连接一个线程”的服务策略。
在Java1.4中引入的NIO的基本要点是使传统的UNIX风格的多路复用非阻塞I/O功能在Java中可用。如果您了解如何使用select()或poll()编程来检测一组文件描述符(通常是套接字)上的I/O准备状态,那么您将在NIO中找到所需的服务:对于非阻塞I/O端点使用SocketChannels,对于fdset或pollfd数组使用Selectors。现在,具有线程池或每个线程处理多个连接的服务器成为可能。这就是“额外的”。
Buffer是非阻塞套接字I/O所需的字节数组,特别是在输出/写入端。如果只能立即写入缓冲区的一部分,则使用阻塞I/O,您的线程就会被阻塞,直到整个线程都可以被写入为止。使用非阻塞I/O,您的线程将获得写入多少的返回值,让您来处理下一轮的剩余内容。Buffer通过显式实现生产者/使用者模式来处理这些机械细节,这样可以理解线程和JVM内核将不同步。
发布于 2014-06-03 09:14:01
即使您使用的是SocketChannels,也必须使用线程池来处理channels。
考虑到场景,您只使用一个线程,它负责轮询select()和处理从Selectors中选择的SocketChannels,如果一个通道需要1秒来处理,并且队列中有10个通道,这意味着您必须在下一个轮询之前等待10秒,这是不可容忍的。因此,应该有一个用于通道处理的线程池。
从这个意义上说,我认为每个客户端的线程阻塞套接字模式并没有太大的不同。主要的区别在于NIO模式,任务较小,更像每个任务的线程,任务可以读、写、处理等等,更详细的是,您可以查看Netty的NioServerSocketChannelFactory实现,它使用一个Boss线程接受连接,并将任务分派到一个工作线程池进行处理。
如果您真的喜欢一个线程,那么底线是至少您应该有一个集合的I/O线程,因为I/O操作通常比指令处理周期慢得多,所以您不希望一个宝贵的线程被I/O阻塞,而这正是NodeJS所做的,使用一个线程接受连接,并且所有的I/O都是异步的,并且由后端I/O线程池并行处理。
是旧的每一个客户端线程死了吗?我不这么认为,NIO编程很复杂,多线程也不是天生的邪恶,请记住,现代操作系统和CPU在多任务处理方面变得越来越好,因此多线程的开销随着时间的推移变得越来越小。
https://stackoverflow.com/questions/14225957
复制相似问题