代码清单 1-1 实现了 Socket API 的基本模式之一。以下是最重要的几点。
ServerSocket上的accept()方法将会一直阻塞到一个连接建立,随后返回一个新的Socket用于客户端和服务器之间的通信。该ServerSocket将继续监听传入的连接。
BufferedReade和PrintWriter都衍生自Socket的输入输出流。前者从一个字符输入流中读取文本,后者打印对象的格式化的表示到文本输出流。
readLine()方 法将会阻塞,直到在处一个由换行符或者回车符结尾的字符串被读取。
客户端的请求已经被处理。
让我们考虑一下这种方案的影响。第一,在任何 时候都可能有大量的线程处于休眠状态,只是等待输 入或者输出数据就绪,这可能算是一种资源浪费。第 二,需要为每个线程的调用栈都分配内存,其默认值大小区间为 64 KB 到 1 MB,具体取决于操作系统。第 三,即使 Java 虚拟机(JVM)在物理上可以支持非常大数量的线程,但是远在到达该极限之前,上下文切换所带来的开销就会带来麻烦,例如,在达 到 10 000 个连接的时候。虽然这种并发方案对于支撑中小数量的客户端来说还算可以接受,但是为了支撑 100 000 或 者更多的并发连接所需要的资源使得它很不理想。幸运的是,还有一种方案。
理解:按照之前原始的办法创建io,很难支撑100000个连接。第一点:浪费线程资源。第二点。占用很多内存,第三点:增加很多线程之间的上下文切换,会带来很多额外的CPU性能开销(使用协程,无锁并发编程(代码刻意控制避免使用锁),cas算法,使用最少线程)。
使用selector的非阻塞I/O就出来了, class java.nio.channels.Selector 是 Java 的非阻塞 I/O 实现的关键。它使用了事件通知 API 以确定在一组非阻塞套接字中有哪些已经就绪能够进行I/O 相关的操作。因为可以在任何的时间检查任意的读操作或者写操作的完成状态。
使用较少的线程便可以处理许多连接,因此也减少了内存管理和上下文切换所带来开销;
当没有 I/O 操作需要处理的时候,线程也可以被用于其他任务。
理解:就是使用selector事件监听器,监听哪些操作可以已经可以做读写了,然后就可以通知用户线程过来读和写,如果没有通知的话,用户线程可以处理自己的逻辑,也就相当于非阻塞了,但是还是存在问题,就是在用户线性在进行读和写的时候,还是需要进行阻塞住,获取到结果后才能释放资源。
但是要很好的处理这些关系 不容易 所以需要一个网络编程专家-------------netty.