当前位置:网站首页 > Java基础 > 正文

动力节点Java301集基础



Java NIO原理图文分析及代码实现
前言:


最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术:动态代理(动态代理可以参考博客:http://weixiaolu.iteye.com/blog/1477774 )和java NIO。为了能够正确地分析hadoop的RPC源码,我觉得很有必要先研究一下java NIO的原理和具体实现。

这篇博客我主要从两个方向来分析java NIO

目录:
一.java NIO 和阻塞I/O的区别
     1. 阻塞I/O通信模型
     2. java NIO原理及通信模型
二.java NIO服务端和客户端代码实现

具体分析:

一.java NIO 和阻塞I/O的区别

1. 阻塞I/O通信模型


假如现在你对阻塞I/O已有了一定了解,我们知道阻塞I/O在调用InputStream.read()方法时是阻塞的,它会一直等到数据到来时(或超时)才会返回;同样,在调用ServerSocket.accept()方法时,也会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。阻塞I/O的通信模型示意图如下:

如果你细细分析,一定会发现阻塞I/O存在一些缺点。根据阻塞I/O通信模型,我总结了它的两点缺点:
1. 当客户端多时,会创建大量的处理线程。且每个线程都要占用栈空间和一些CPU时间

2. 阻塞可能带来频繁的上下文切换,且大部分上下文切换可能是无意义的。

在这种情况下非阻塞式I/O就有了它的应用前景。

2. java NIO原理及通信模型

Java NIO是在jdk1.4开始使用的,它既可以说成“新I/O”,也可以说成非阻塞式I/O。下面是java NIO的工作原理:

1. 由一个专门的线程来处理所有的 IO 事件,并负责分发。
2. 事件驱动机制:事件到的时候触发,而不是同步的去监视事件。
3. 线程通讯:线程之间通过 wait,notify 等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换。

阅读过一些资料之后,下面贴出我理解的java NIO的工作原理图:

(注:每个线程的处理流程大概都是读取数据、解码、计算处理、编码、发送响应。)

Java NIO的服务端只需启动一个专门的线程来处理所有的 IO 事件,这种通信模型是怎么实现的呢?呵呵,我们一起来探究它的奥秘吧。java NIO采用了双向通道(channel)进行数据传输,而不是单向的流(stream),在通道上可以注册我们感兴趣的事件。一共有以下四种事件:

事件名

对应值

服务端接收客户端连接事件

SelectionKey.OP_ACCEPT(16)

动力节点Java301集基础

客户端连接服务端事件

SelectionKey.OP_CONNECT(8)

读事件

SelectionKey.OP_READ(1)

写事件

SelectionKey.OP_WRITE(4)

/colgroup>

tbody>

/tbody>

二.java NIO服务端和客户端代码实现

/strong>

br>

br> 为了更好地理解java NIO,下面贴出服务端和客户端的简单代码实现。

br>

br>

服务端:

Java代码  

br>

package

/strong> cn.nio;  

import

/strong> java.io.IOException;  

import

/strong> java.net.InetSocketAddress;  

import

/strong> java.nio.ByteBuffer;  

import

/strong> java.nio.channels.SelectionKey;  

import

/strong> java.nio.channels.Selector;  

import

/strong> java.nio.channels.ServerSocketChannel;  

import

/strong> java.nio.channels.SocketChannel;  

import

/strong> java.util.Iterator;  

public class

/strong> NIOServer {  

private

/strong> Selector selector;  

public void

/strong> initServer(

int

/strong> port)

throws

/strong> IOException {  

false

/strong>);  

new

/strong> InetSocketAddress(port));  

this

/strong>.selector = Selector.open();  

public void

/strong> listen()

throws

/strong> IOException {  

while

/strong> (

true

/strong>) {  

this

/strong>.selector.selectedKeys().iterator();  

while

/strong> (ite.hasNext()) {  

if

/strong> (key.isAcceptable()) {  

false

/strong>);  

new

/strong> String("向客户端发送了一条信息").getBytes()));  

this

/strong>.selector, SelectionKey.OP_READ);  

else if

/strong> (key.isReadable()) {  

public void

/strong> read(SelectionKey key)

throws

/strong> IOException{  

byte

/strong>[] data = buffer.array();  

new

/strong> String(data).trim();  

public static void

/strong> main(String[] args)

throws

/strong> IOException {  

new

/strong> NIOServer();  

br>

客户端:

Java代码  

br>

package

/strong> cn.nio;  

import

/strong> java.io.IOException;  

import

/strong> java.net.InetSocketAddress;  

import

/strong> java.nio.ByteBuffer;  

import

/strong> java.nio.channels.SelectionKey;  

import

/strong> java.nio.channels.Selector;  

import

/strong> java.nio.channels.SocketChannel;  

import

/strong> java.util.Iterator;  

public class

/strong> NIOClient {  

private

/strong> Selector selector;  

public void

/strong> initClient(String ip,

int

/strong> port)

throws

/strong> IOException {  

false

/strong>);  

this

/strong>.selector = Selector.open();  

new

/strong> InetSocketAddress(ip,port));  

public void

/strong> listen()

throws

/strong> IOException {  

while

/strong> (

true

/strong>) {  

this

/strong>.selector.selectedKeys().iterator();  

while

/strong> (ite.hasNext()) {  

if

/strong> (key.isConnectable()) {  

if

/strong>(channel.isConnectionPending()){  

false

/strong>);  

new

/strong> String("向服务端发送了一条信息").getBytes()));  

this

/strong>.selector, SelectionKey.OP_READ);  

else if

/strong> (key.isReadable()) {  

public void

/strong> read(SelectionKey key)

throws

/strong> IOException{  

public static void

/strong> main(String[] args)

throws

/strong> IOException {  

new

/strong> NIOClient();  

br>

小结:

/strong>

br>

br> 终于把动态代理和java NIO分析完了,呵呵,下面就要分析hadoop的RPC机制源码了,博客地址:http://weixiaolu.iteye.com/blog/ 。不过如果对java NIO的理解存在异议的,欢迎一起讨论。

版权声明


相关文章:

  • java 面向对象基础视频2024-10-25 15:58:04
  • java微服务基础2024-10-25 15:58:04
  • java基础面试 高级开发2024-10-25 15:58:04
  • 大学java基础知识树状图2024-10-25 15:58:04
  • java工作原理基础2024-10-25 15:58:04
  • java基础语法练习32024-10-25 15:58:04
  • 九章算法基础班java2024-10-25 15:58:04
  • JAVA面试题基础Map遍历循环2024-10-25 15:58:04
  • 零基础学java的工作2024-10-25 15:58:04
  • java基础总结大纲图2024-10-25 15:58:04