非阻塞通信——Java

一、实验目的和要求

1.掌握Java非阻塞通信机制,掌握java.nio中ServerSocketChannel、SocketChannel、Selector、SelectionKey等关键类的使用;
2.掌握使用java.nio包中的类创建非阻塞模式的服务器和客户程序的方法。

二、实验内容

1. 分析说明
(1)说明导致线程阻塞的主要原因;
答:导致线程阻塞的原因主要有以下几个方面:

  • 线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行
  • 线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,等到获得了同步锁,才能恢复运行
  • 线程执行了一个对象的wait()方法,进入阻塞状态,只有等到其他线程执行了该对象的notify()或notifyAll()方法,才可能将其唤醒
  • 线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。例如,当线程执行System.in.read()方法时,如果用户没有向控制台输入数据,则该线程会一直等读到了用户的输入数据才从read()方法返回。

(2)分析说明java.nio中进行非阻塞通信时,使用的主要类的功能及其相互关系。
答:

  • ServerSocketChannel:ServerSocket的替代类,支持阻塞通信与非阻塞通信。
  • SocketChannel:Socket的替代类,支持阻塞通信与非阻塞通信。
  • Selector:为ServerSocketChannel监控接受连接就绪事件,为SocketChannel监控连接就绪,读就绪和写就绪事件。
  • SelectionKey:代表ServerSocketChannel及SocketChannel向Selector注册事件的句柄。当一个SelectionKey对象位于Selector对象的selected-keys集合中时,就表示与这个SekectionKey对象相关的事件发生了。
  • ByteBuffer表示字节缓冲区,SocketChannel的read()和write()方法都会操纵ByteBuffer。ByteBuffer类继承于Buffer类。ByteBuffer中存放的是字节,为了把它们转换为字符串,还需要用到Charset类,Charset类代表字符编码,它提供了把字节流转换为字符串(解码过程)和把字符串转换为字节流(编码过程)的实用方法
    非阻塞通信——Java_第1张图片
    2. 课本例4-1EchoServer.java(线程池阻塞模式)及例4-2EchoServer.java(非阻塞模式)的分析与调试运行。
    非阻塞通信——Java_第2张图片非阻塞通信——Java_第3张图片
    非阻塞通信——Java_第4张图片
    非阻塞通信——Java_第5张图片

(1)分析例4-1,说明可能导致线程阻塞的语句。
答: 有以下几点有可能会导致阻塞的发生。
1)服务端等待客户端连接:
在这里插入图片描述
线程执行 accept()方法,等待客户的连接,直到收到了客户连接,才从accept()方法返回。
2)线程从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞。
非阻塞通信——Java_第6张图片
Socket的输入流br利用readLine()方法读取一行字符串,如果一直没有数据输入,就会阻塞。
3)线程向Socket的输出流写一批数据时,可能会进入阻塞。
非阻塞通信——Java_第7张图片
线程向Socket的输出流写一批数据时,由于写数据需要一定的时间,等到输出所有的数据或发生异常,才从输出流的write()方法返回或异常中断。
(2)分析例4-2,图示EchoServer.service方法的主要框架,说明其中主要对象的关系。
非阻塞通信——Java_第8张图片
在service()方法中,ServerSocketChannel向Selector注册接收连接就绪事件。监听事件发生,将SelectionKey对象加入到selected-keys集合中。利用accept()方法获得与客户连接的SocketChannel对象。SeverSocketChannel向register()方法传递了一个ByteBuffer类型参数,ByteBuffer将作为附件,与新建的SelectionKey对象关联。
(3)改进、调试、运行上述两个例子,给出运行结果及分析说明。
4-1运行结果:
在这里插入图片描述
在这里插入图片描述
4-2运行结果:
非阻塞通信——Java_第9张图片
非阻塞通信——Java_第10张图片
三、实验总结
1.实验过程中遇到的问题及解决办法;
答:在实验过程中,对于阻塞模式和非阻塞通信编程的思路不是很了解
解决:尽管阻塞模式与非阻塞模式都可以同时处理多个客户连接,但阻塞模式需要使用较多的线程,而非阻塞模式只需使用较少的线程,非阻塞模式能更有效地利用CPU,系统开销小,因此有更高的并发性能。阻塞模式比较适用于同步通信,并且通信双方稳定地发送小批量的数据,双方都不需要花很长时间等待对方的回应。非阻塞模式编程相对难一些,对ByteBuffer缓冲区的处理比较麻烦。非阻塞模式比较适用于异步通信,并且通信双方发送大批量的数据,尽管一方接收到另一方的数据可能要花一段时间,但在这段时间内,接收方不必傻傻地等待,可以处理其他事情。

你可能感兴趣的:(非阻塞通信——Java)