自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java NIO類(lèi)庫(kù)Selector機(jī)制解析(下)

開(kāi)發(fā) 后端
自從J2SE 1.4版本以來(lái),JDK發(fā)布了全新的I/O類(lèi)庫(kù),簡(jiǎn)稱(chēng)NIO,其不但引入了全新的高效的I/O機(jī)制,同時(shí),也引入了多路復(fù)用的異步模式。

五、 迷惑不解 : 為什么要自己消耗資源?

令人不解的是為什么我們的Java的New I/O要設(shè)計(jì)成這個(gè)樣子?如果說(shuō)老的I/O不能多路復(fù)用,如下圖所示,要開(kāi)N多的線程去挨個(gè)偵聽(tīng)每一個(gè)Channel (文件描述符) ,如果這樣做很費(fèi)資源,且效率不高的話。那為什么在新的I/O機(jī)制依然需要自己連接自己,而且,還是重復(fù)連接,消耗雙倍的資源?

通過(guò)WEB搜索引擎沒(méi)有找到為什么。只看到N多的人在報(bào)BUG,但SUN卻沒(méi)有任何解釋。

下面一個(gè)圖展示了,老的IO和新IO的在網(wǎng)絡(luò)編程方面的差別??雌饋?lái)NIO的確很好很強(qiáng)大。但似乎比起C/C++來(lái)說(shuō),Java的這種實(shí)現(xiàn)會(huì)有一些不必要的開(kāi)銷(xiāo)。

六、 它山之石 : 從Apache的Mina框架了解Selector

上面的調(diào)查沒(méi)過(guò)多長(zhǎng)時(shí)間,正好同學(xué)趙錕的一個(gè)同事也在開(kāi)發(fā)網(wǎng)絡(luò)程序,這位仁兄使用了Apache的Mina框架。當(dāng)我們把Mina框架的源碼研讀了一下后。發(fā)現(xiàn)在Mina中有這么一個(gè)機(jī)制:

1)Mina框架會(huì)創(chuàng)建一個(gè)Work對(duì)象的線程。

2)Work對(duì)象的線程的run()方法會(huì)從一個(gè)隊(duì)列中拿出一堆Channel,然后使用Selector.select()方法來(lái)偵聽(tīng)是否有數(shù)據(jù)可以讀/寫(xiě)。

3)最關(guān)鍵的是,在select的時(shí)候,如果隊(duì)列有新的Channel加入,那么,Selector.select()會(huì)被喚醒,然后重新select***的Channel集合。

4)要喚醒select方法,只需要調(diào)用Selector的wakeup()方法。

對(duì)于熟悉于系統(tǒng)調(diào)用的C/C++程序員來(lái)說(shuō),一個(gè)阻塞在select上的線程有以下三種方式可以被喚醒:

1) 有數(shù)據(jù)可讀/寫(xiě),或出現(xiàn)異常。

2) 阻塞時(shí)間到,即time out。

3) 收到一個(gè)non-block的信號(hào)。可由kill或pthread_kill發(fā)出。

所以,Selector.wakeup()要喚醒阻塞的select,那么也只能通過(guò)這三種方法,其中:

1)第二種方法可以排除,因?yàn)閟elect一旦阻塞,應(yīng)無(wú)法修改其time out時(shí)間。

2)而第三種看來(lái)只能在Linux上實(shí)現(xiàn),Windows上沒(méi)有這種信號(hào)通知的機(jī)制。

所以,看來(lái)只有***種方法了。再回想到為什么每個(gè)Selector.open(),在Windows會(huì)建立一對(duì)自己和自己的loopback的TCP連接;在Linux上會(huì)開(kāi)一對(duì)pipe(pipe在Linux下一般都是成對(duì)打開(kāi)),估計(jì)我們能夠猜得出來(lái)——那就是如果想要喚醒select,只需要朝著自己的這個(gè)loopback連接發(fā)點(diǎn)數(shù)據(jù)過(guò)去,于是,就可以喚醒阻塞在select上的線程了。

七、 真相大白 : 可愛(ài)的Java你太不容易了

使用Linux下的strace命令,我們可以方便地證明這一點(diǎn)。參看下圖。圖中,請(qǐng)注意下面幾點(diǎn):

1) 26654是主線程,之前我輸出notify the select字符串是為了做一個(gè)標(biāo)記,而不至于迷失在大量的strace log中。

2) 26662是偵聽(tīng)線程,也就是select阻塞的線程。

3) 圖中選中的兩行。26654的write正是wakeup()方法的系統(tǒng)調(diào)用,而緊接著的就是26662的epoll_wait的返回。

從上圖可見(jiàn),這和我們之前的猜想正好一樣。可見(jiàn),JDK的Selector自己和自己建的那些TCP連接或是pipe,正是用來(lái)實(shí)現(xiàn)Selector的notify和wakeup的功能的。

這兩個(gè)方法完全是來(lái)模仿Linux中的的kill和pthread_kill給阻塞在select上的線程發(fā)信號(hào)的。但因?yàn)榘l(fā)信號(hào)這個(gè)東西并不是一個(gè)跨平臺(tái)的標(biāo)準(zhǔn)(pthread_kill這個(gè)系統(tǒng)調(diào)用也不是所有Unix/Linux都支持的),而pipe是所有的Unix/Linux所支持的,但Windows又不支持,所以,Windows用了TCP連接來(lái)實(shí)現(xiàn)這個(gè)事。

關(guān)于Windows,我一直在想,Windows的防火墻的設(shè)置是不是會(huì)讓Java的類(lèi)似的程序執(zhí)行異常呢?呵呵。如果不知道Java的SDK有這樣的機(jī)制,誰(shuí)知道會(huì)有多少個(gè)程序?yàn)榇艘鸬膯?wèn)題度過(guò)多少個(gè)不眠之夜,尤其是Java程序員。

八、 后記

文章到這里是可以結(jié)束了,但關(guān)于Java NIO的Selector引出來(lái)的其它話題還有許多,比如關(guān)于GNU 的Java編譯器又是如何,它是否會(huì)像Sun的Java解釋器如此做傻事?我在這里先賣(mài)一個(gè)關(guān)子,關(guān)于GNU的Java編譯器,我會(huì)在另外一篇文章中講述,近期發(fā)布,敬請(qǐng)期待。

關(guān)于本文中所使用的實(shí)驗(yàn)平臺(tái)如下:

◆  Windows:Windows XP + SP2, Sun J2SE (build 1.7.0-ea-b23)

◆  Linux:Ubuntu 7.10 + Linux Kernel 2.6.22-14-generic, J2SE (build 1.6.0_03-b05)

本文主要的調(diào)查工作由我的大學(xué)同學(xué)趙錕完成,我?guī)推潋?yàn)證調(diào)查成果及猜想。在此也向大家介紹我的大學(xué)同學(xué)趙錕,他也是一個(gè)技術(shù)高手,在軟件開(kāi)發(fā)方面,特別是Unix/Linux C/C++方面有著相當(dāng)?shù)墓Φ?,相信自此以后,?huì)有很多文章會(huì)由我和他一同發(fā)布。

本篇文章由我成文。但其全部著作權(quán)和版權(quán)歸趙錕和我共同所有。我們歡迎大家轉(zhuǎn)載,但希望保持整篇文章的完整性,并請(qǐng)勿用于任何商業(yè)用途。謝謝。

原文鏈接:http://haoel.blog.51cto.com/313033/124578

【編輯推薦】

  1. Java NIO類(lèi)庫(kù)Selector機(jī)制解析(上)
  2. Java的NIO以及線程并發(fā)
  3. 基于事件的NIO多線程服務(wù)器
  4. Java NIO的多路復(fù)用及reactor
  5. 在Java中使用NIO進(jìn)行網(wǎng)絡(luò)編程
責(zé)任編輯:林師授 來(lái)源: 陳皓的個(gè)人博客
相關(guān)推薦

2011-12-12 10:19:00

JavaNIO

2022-02-22 08:00:48

JavaNIOBuffer

2011-12-07 15:58:25

JavaNIO

2025-02-28 09:14:09

JavaNIO機(jī)制

2011-12-08 10:24:53

JavaNIO

2011-11-23 09:39:33

JavaClassLOader機(jī)制

2010-01-25 17:28:18

Android類(lèi)庫(kù)

2011-03-16 09:26:41

ReadWriteLoJava

2021-07-05 06:51:43

Java機(jī)制類(lèi)加載器

2010-09-17 13:02:11

JAVA反射機(jī)制

2015-10-26 09:25:42

2022-03-24 13:36:18

Java悲觀鎖樂(lè)觀鎖

2011-07-01 15:04:49

Qt 內(nèi)省

2010-10-13 10:24:38

垃圾回收機(jī)制JVMJava

2011-12-15 09:55:47

javanio

2011-12-15 11:19:08

JavaNIO

2011-12-07 14:57:44

JavaNIO

2011-12-15 09:40:06

Javanio

2024-05-27 08:04:41

2017-03-08 10:30:43

JVMJava加載機(jī)制
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)