`
olife
  • 浏览: 76435 次
  • 性别: Icon_minigender_1
  • 来自: SKY
文章分类
社区版块
存档分类
最新评论

[轉]Java NIO原裡與使用

阅读更多
Java NIO非堵塞應用通常適用用在I/O讀寫等方面,我們知道,系統運行的性能瓶頸通常在I/O讀寫,包括對端口和文件的操作上,過去,在打開一個I/O通道後,read()將一直等待在端口一邊讀取字節內容,如果沒有內容進來,read()也是傻傻的等,這會影響我們程序繼續做其他事情,那麼改進做法就是開設線程,讓線程去等待,但是這樣做也是相當耗費資源的。

Java NIO非堵塞技術實際是採取Reactor模式,或者說是Observer模式為我們監察I/O端口,如果有內容進來,會自動通知我們,這樣,我們就不必開啟多個線程死等,從外界看,實現了流暢的I/O讀寫,不堵塞了。

Java NIO出現不只是一個技術性能的提高,你會發現網絡上到處在介紹它,因為它具有里程碑意義,從JDK1.4開始,Java開始提高性能相關的功能,從而使得Java在底層或者並行分佈式計算等操作上已經可以和C或Perl等語言並駕齊驅。

如果你至今還是在懷疑Java的性能,說明你的思想和觀念已經完全落伍了,Java一兩年就應該用新的名詞來定義。從JDK1.5開始又要提供關於線程、並發等新性能的支持,Java應用在遊戲等適時領域方面的機會已經成熟,Java在穩定自己中間件地位後,開始蠶食傳統C的領域。

本文主要簡單介紹NIO的基本原理,在下一篇文章中,將結合Reactor模式和著名線程大師 Doug Lea 的一篇文章深入討論。

NIO主要原理和適用。

NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有事件發生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛註冊過的socketchannel,然後,我們從這個Channel中讀取數據,放心,包準能夠讀到,接著我們可以處理這些數據。

Selector內部原理實際是在做一個對所註冊的channel的輪詢訪問,不斷的輪詢(目前就這一個算法),一旦輪詢到一個channel有所註冊的事情發生,比如數據來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙來讀取這個channel的內容。

了解了這個基本原理,我們結合代碼看看使用,在使用上,也在分兩個方向,一個是線程處理,一個是用非線程,後者比較簡單,看下面代碼:
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;

/** 
 * 
 * @author Administrator 
 * @version 
 */
public class NBTest {

    /** Creates new NBTest */
    public NBTest() {
    }

    public void startServer() throws Exception {
        int channels = 0;
        int nKeys = 0;
        int currentSelector = 0;

		//使用Selector 
        Selector selector = Selector.open();

		//建立Channel並綁定到9000端口 
        ServerSocketChannel ssc = ServerSocketChannel.open();
        InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 9000);
        ssc.socket().bind(address);

		//使設定non-blocking的方式。 
        ssc.configureBlocking(false);

		//向Selector註冊Channel及我們有興趣的事件 
        SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
        printKeyInfo(s);

        while (true) //不斷的輪詢 
        {
            debug("NBTest: Starting select");

			//Selector通過select方法通知我們我們感興趣的事件發生了。 
            nKeys = selector.select();
			//如果有我們註冊的事情發生了,它的傳回值就會大於0 
            if (nKeys > 0) {
                debug("NBTest: Number of keys after select operation: " + nKeys);

				//Selector傳回一組SelectionKeys 
				//我們從這些key中的channel()方法中取得我們剛剛註冊的channel。 
                Set selectedKeys = selector.selectedKeys();
                Iterator i = selectedKeys.iterator();
                while (i.hasNext()) {
                    s = (SelectionKey) i.next();
                    printKeyInfo(s);
                    debug("NBTest: Nr Keys in selector: " + selector.keys().size());

					//一個key被處理完成後,就都被從就緒關鍵字(ready keys)列表中除去 
                    i.remove();
                    if (s.isAcceptable()) {
						//從channel()中取得我們剛剛註冊的channel。 
                        Socket socket = ((ServerSocketChannel) s.channel()).accept().socket();
                        SocketChannel sc = socket.getChannel();

                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                        System.out.println(++channels);
                    } else {
                        debug("NBTest: Channel not acceptable");
                    }
                }
            } else {
                debug("NBTest: Select finished without any keys.");
            }

        }

    }

    private static void debug(String s) {
        System.out.println(s);
    }

    private static void printKeyInfo(SelectionKey sk) {
        String s = new String();

        s = "Att: " + (sk.attachment() == null ? "no" : "yes");
        s += ", Read: " + sk.isReadable();
        s += ", Acpt: " + sk.isAcceptable();
        s += ", Cnct: " + sk.isConnectable();
        s += ", Wrt: " + sk.isWritable();
        s += ", Valid: " + sk.isValid();
        s += ", Ops: " + sk.interestOps();
        debug(s);
    }

    /** 
     * @param args the command line arguments 
     */
    public static void main(String args[]) {
        NBTest nbTest = new NBTest();
        try {
            nbTest.startServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


這是一個守候在端口9000的noblock server例子,如果我們編制一個客戶端程序,就可以對它進行互動操作,或者使用telnet 主機名90000 可以鏈接上。
通過仔細閱讀這個例程,相信你已經大致了解NIO的原理和使用方法,下一篇(http://blog.csdn.net/hdy007/archive/2006/12/24/1458555.aspx),我們將使用多線程來處理這些數據,再搭建一個自己的Reactor模式。

ref : http://blog.csdn.net/hdy007/archive/2006/12/24/1458551.aspx
分享到:
评论

相关推荐

    java NIO原理和使用

    java nio 附带例子 以及原理 java nio 附带例子 以及原理 java nio 附带例子 以及原理 java nio 附带例子 以及原理

    java NIO技巧及原理

    java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较

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

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

    Java NIO原理和使用

    Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能...通过仔细阅读这个例程,相信你已经大致了解NIO的原理和使用方法,下一篇,我们将使用多线程来处理这些数据,再搭建一个自己的Reactor模式。

    Java NIO原理解析

    Java NIO原理解析jdk供的无阻塞I/O(NIO)有效解决了多线程服务器存在的线程开销问题,但在使用上略显得复杂一些。在NIO中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程...

    Java NIO的介绍及工作原理

    Java NIO的介绍及工作原理Java NIO的介绍及工作原理

    Java NIO原理分析及代码实例

    NULL 博文链接:https://dengqsintyt.iteye.com/blog/2083316

    java NIO详细教程

    java NIO详细教程,包括使用背景,实现原理,代码实现

    Java NIO 指南 - v1.0.pdf

    Java NIO(New IO)是一个可以替代标准 Java IO API 的 IO API(从 Java 1.4 开始),Java NIO 提供了与标准 IO 不同的 IO 工作方式。本教程讲解了 Java NIO 的三个核心组件,并介绍了跟核心组件相关的内容,旨在帮助 ...

    JAVA NIO ppt

    JAVA NIO 课堂ppt,讲述NIO原理,技术等。

    java nio 原理浅析

    本文将主要分析Netty实现方面的东西,由于精力有限,本人并没有对其源码...对于Netty使用者来说,Netty提供了几个典型的example,并有详尽的API doc和guide doc,本文的一些内容及图示也来自于Netty的文档,特此致谢。

    JavaNIO的原理.pdf

    JavaNIO的原理.pdf

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

    本文主要介绍Java NIO原理的知识,这里整理了详细资料及简单示例代码和原理图,有需要的小伙伴可以参考下

    Java NIO 中文全书签

    这本书是介绍java nio的基础书籍,原理讲的还是挺明白的,比较好懂,就是例子比较少。nio对于java程序员来说可能不是很好理解,但是对于C程序员来说,就是epoll的一个封装。 我本人是C程序员,对java比较感兴趣,...

    Java NIO——Selector机制解析三(源码分析)

    NULL 博文链接:https://goon.iteye.com/blog/1775421

    Java_NIO原理解析

    Java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer(观察员)模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必 开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。

    Java NIO工作原理的全面分析

    JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的、面向块的 I/O。本实用教程从高级概念到底层的编程细节,非常详细地介绍了 NIO 库。您将学到诸如缓冲区和通道这样的关键 I/O 元素的知识,并...

    java NIO 详细讲解

    对java.nio包的应用、原理的详细讲解。非常值得收藏的珍藏品。 java大师中的必须掌握的技术,直播、视频的必备技术

Global site tag (gtag.js) - Google Analytics