《電子技術應用》
您所在的位置:首頁 > 其他 > 設計應用 > Java非阻塞I/O在鄉村可視化遠程醫療系統中的應用
Java非阻塞I/O在鄉村可視化遠程醫療系統中的應用
來源:微型機與應用2011年第6期
顧和明
(長江師范學院 數學與計算機學院,重慶408100)
摘要: 分析了鄉村可視化遠程醫療系統采用多線程技術實現網絡通信存在的不足,闡述了Java非阻塞I/O的基本原理。系統采用非阻塞I/O通信技術只使用一個線程并行實現大量客戶無阻塞的通信,有效地減少了系統開銷,較好地提升了系統的性能。
Abstract:
Key words :

摘  要: 分析了鄉村可視化遠程醫療系統采用多線程技術實現網絡通信存在的不足,闡述了Java非阻塞I/O的基本原理。系統采用非阻塞I/O通信技術只使用一個線程并行實現大量客戶無阻塞的通信,有效地減少了系統開銷,較好地提升了系統的性能。
關鍵詞: 非阻塞I/O;遠程醫療系統;線程阻塞;通道

1 鄉村可視化遠程醫療系統的應用前景
    目前我國廣大的農村地區醫療條件比較差,這些地區的大量患者因為得不到及時有效的治療,給患者以及家屬帶來了不必要的痛苦。使用網絡多媒體通信技術實現的鄉村可視化遠程醫療系統可以讓高水平的醫療專家給鄉村的患者進行遠程診病,以及指導治療與護理。鄉村衛生所、鄉鎮醫院等醫療單位可以和具有優質醫療資源的醫院或直接與專家建立醫療合作關系,雙方合作使用可視化醫療系統,讓專家為病人進行遠程診療服務。在鄉村這一端,一般由專業醫務人員指導病人接受專家遠程診療,醫療專家通過可視化醫療系統實時對病人進行診斷、處方、治療甚至指導手術等。患者也可以在家中使用遠程醫療系統直接接受遠程專家的指導,尤其在處理突發性疾病時,可以在第一時間內得到醫療專家的幫助。目前隨著生活水平的大幅度提高,不少需要“私人醫生”的人員也可以方便地使用該系統得到醫療專家的服務。可見,可視化醫療系統有著很廣闊的應用市場和較好的發展前景。
2 鄉村可視化遠程醫療系統功能簡介
    鄉村遠程醫療系統可以同時提供若干對醫療服務,每一對服務有2個或2個以上的客戶端進行通信。客戶端分別由醫療專家和患者使用,醫療專家使用的客戶端稱為專家端,患者接受診療的客戶端稱為醫務端。每個客戶(醫務端和專家端)首先登錄服務器,服務器將每個登錄客戶的用戶名、IP地址等相關信息發送給相關的其他客戶,然后客戶端之間建立直接連接,并可進行文件傳送、文字和多媒體等通信。通過這種綜合的通信方式,醫療專家可以遠程為患者提供醫療服務。為了建立醫療檔案,服務器需要保存診療時間、參與人員、患者檢驗報告、病情診斷、處方等信息。患者還可以通過服務器進行專家預約,專家和患者均可以在服務器上進行診療信息查詢。由于視頻信息量比較大,且保存意義不是十分大,因此并不保存在服務器上。系統結構如圖1所示。

3 使用多線程和阻塞通信模式存在的局限
    可視化遠程醫療服務器需要同時為多個專家端和醫務端提供服務,在傳統的阻塞通信模式中使用多線程技術來處理多客戶連接,一般需要服務器為每個客戶端建立一個線程。但使用多線程技術存在以下局限:
    (1)Java虛擬機會為每個線程分配獨立的堆棧空間,工作線程數目越多,系統開銷就越大,而且增加了Java虛擬機調度線程的負擔,增加了線程之間同步的復雜性,提高了線程死鎖的可能性;
    (2)當主線程接收客戶連接,在醫療服務過程中,服務器從網絡發送或接收數據時,線程常常進入阻塞狀態,這就使工作線程的許多時間都浪費在阻塞操作上,CPU的利用率降低,此外Java虛擬機需要頻繁地轉讓CPU的使用權。
    由此可見,工作線程并不是越多越好。實驗表明,適量的工作線程會提高服務器的并發性能,但是當工作線程的數目達到某個極限而超出系統的負荷時,反而會降低并發性能,使得許多客戶端得不到服務器的及時響應。為了改善服務器性能,在遠程醫療系統中采用了Java非阻塞I/O通信技術。
4 Java非阻塞I/O工作原理簡介
    在傳統的阻塞通信模式中,服務器在接受客戶連接后創建Socket對象與客戶進行通信,Socket對象由線程進行管理。當有多個客戶連接時,就需要多個線程分別處理服務器與各個客戶的通信。Java非阻塞I/O通信服務器程序只需要一個線程就能夠實現多個客戶端的連接、同時接收多個客戶端發送的數據,以及同時向多個客戶端發送響應數據。這種非阻塞通信采用了基于Channel(通道)、Selector(選擇器) 、Buffer(緩沖器)的新模式。
    非阻塞I/O通信中Channel是一個接口,功能類似于傳統I/O中的Stream,但通道具有雙向性,既可讀入,也可寫出。SocketChannel和ServerSocketChannel均可實現Channel接口,它們是Socket和ServerSocket的替代類,但比Socket和ServerSocket具有更多的功能,它支持非阻塞通信、可選擇通信、異步通信和套接字對等通信等。
    由于網絡接收和傳送數據均比較緩慢,常常導致線程阻塞,影響系統性能。在Java非阻塞通信模式中使用Buffer來緩沖數據。SocketChannel和ServerSocketChannel對象一端連接著緩沖區,另一端連接著網絡。
    ServerSocketChannel和SocketChannel在Selector中注冊連接就緒事件、讀就緒事件和寫就緒事件。注冊時創建一個SelectionKey對象,這個SelectionKey對象用來跟蹤注冊事件的句柄,其中包含有注冊該對象的通道和緩沖區等信息。Selector會一直監控已經注冊的事件。當通道中有數據需要讀取時,Selector中就有已注冊的讀就緒事件發生,這時調用相關的程序可將通道中的數據讀到緩沖區中,然后再提供給程序進行處理。同樣地,當有數據需要通過網絡發送時,數據先進入緩沖區,這時Selector中就發生寫就緒事件,程序再利用通道向網絡發送數據[1]。
    非阻塞通信模式處理流程如下:
    while(檢測Selector對象,等待連接就緒事件、讀就緒事
件或寫就緒事件發生) {    //阻塞
        if(有客戶連接)//非阻塞
            接收客戶連接,創建SocketChannel對象與客
戶通信;
        if(某個SocketChannel輸入流中有可讀數據)
//非阻塞
            從輸入流讀數據;
        if(某個SocketChannel輸出流中有可寫數據)
//非阻塞
            向輸出流寫數據;
    }
    上述處理流程采用輪詢工作方式,當某一種操作就緒時,執行該操作,否則就查看是否還有其他就緒操作可以執行,線程不會因為某一個連接、讀、寫等操作還沒有就緒,就進入阻塞狀態。在非阻塞通信模式中,只需要一個線程管理Selector對象就可以了,而不需要多線程。并且只有檢測Selector對象時才有可能導致線程阻塞,因此可以大大提高系統的性能。
5 非阻塞通信在鄉村可視化遠程醫療系統中的應用研究
    在鄉村可視化遠程醫療系統中,服務器端需要和各個客戶端建立連接、接受客戶端的操作請求并將操作結果返回給客戶端。服務器只需要使用一個線程就可以處理客戶端連接請求和向各個客戶端讀寫數據,服務器自身進行的數據庫操作可以使用另外的線程。
    專家端和醫務端在服務器端的數據庫中進行查詢、插入和修改等操作,這些操作信息是各種SQL語句,服務器返回給專家端和醫務端的是查詢、保存或修改結果,它們可能是一個字符串、一條記錄,也可能是多條記錄。為了方便操作,這些信息均封裝成XML格式,根標志為<teleMedi></teleMedi>。這種格式封裝數據便于檢驗數據的完整性與正確性,也容易解析。在非阻塞通信中,除boolean類型以外,每種基本數據類型都有對應的緩沖區類,在本系統中使用ByteBuffer類對象數據緩沖區。程序中需要向網絡發送數據時,數據進入緩沖區前先要把字符數據編碼成字節數據,然后再由通道向網絡發送,而從網絡上接收的字節流數據先存放進緩沖區,解碼后再由程序處理。
    在非阻塞通信模式中,一次完整的數據發送可能需要多次讀緩沖區,這避免了阻塞通信模式中讀取數據時間拖得過長而導致的線程阻塞。每次讀緩沖區后都要進行數據完整性檢查,由于采用XML格式封裝數據,所以很容易檢驗是不是讀取到了完整的數據。
    鄉村可視化遠程醫療系統中每次通過網絡讀寫的數據長短不同。醫療中需要傳送的數據最常見的長度小于1 KB,因此緩沖區最初設定為1 KB,當數據超過這個長度時,將緩沖區的容量擴大一倍,如果超過2 KB,再將緩沖區擴大一倍,如此類推。使用這種可伸縮的方式可以更有效地利用內存資源。
6 非阻塞通信在鄉村可視化遠程醫療系統中的實現[2]
    在非阻塞模式下,服務器主程序MedicalSever只使用一個線程,使用Selector監控接收連接就緒事件、讀就緒事件和寫就緒事件。限于篇幅,本文僅介紹幾段主要的代碼。
    (1)MedicalServer類的構造方法負責啟動服務器,把它綁定到一個本地端口,主要代碼如下:
    selector=Selector.open();//創建一個Selector對象
    ssChannel=ServerSocketChannel.open();
//創建ServerSocketChannel對象
    ssChannel.configureBlocking(false);
//設置ServerSocketChannel為阻塞工作模式
    ssChannel.socket().bind(new InetSocketAddress(port));
//綁定到本地端口
    (2)MedicalSever類的serve()方法負責輪詢Selector,主要代碼如下:
    public void serve() throws IOException{
        ssChannel.register(selector,SelectorKey.OP_ACCEPT);
//在Selector中注冊連接就緒事件
        while(selector.select()>0){
            Set readyKeys=selector.selectedKeys();
//獲取Selector中就緒事件集合
            Iterator it=readyKeys.iterator();
            while(it.hasNext()){
            SelectorKey key=null;
            try{
                key=(SelectionKey)it.next();
//獲取某個就緒事件
                it.remove();//獲取就緒事件后刪除
                if(key.isReadable()){處理連接就緒事件}
                if(key.isReadable()){處理讀就緒事件}
                if(key.isWritable()){處理寫就緒事件}
            }catch(IOException e){   }}}
    (3)處理連接就緒事件方法中的主要代碼如下:
    ServerSocketChannel ssc=(ServerSocketChannel)key.channel();
    SocketChannel sChannel=(SocketChannel)ssc.accept();
//獲取關系的SocketChannel
    socketChannel.configureBlocking(false);
//將SocketChannel設置為非阻塞模式
    ByteBuffer buffer=ByteBuffer.allocate(1024);//分配緩沖區
    socketChannel.register(selector,SelectorKey.OP_READ|
SelectionKey.OP_WRITER,buffer);
//注冊讀就緒和寫就緒事件
    (4)處理讀就緒事件方法中的主要代碼如下:
    public void receive(SelectionKey key)throws IOException{
        ByteBuffer sBuffer=(ByteBuffer)key.attachment();
//獲取與SelectorKey綁定的緩沖區
        SocketChannel sChannel=
(SocketChannel)key.channel();//獲得通道
        ByteBuffer buff=ByteBuffer.allocate(1024)
//創建輔助緩沖區
        sChannel.read(buff);//從通道中讀數據暫存到buff中
        sBuffer.put(buff); }//把buff中的內容拷貝到緩沖區
    在非阻塞模式下,sChannel.read(buff)方法無法保證一次把全部數據都讀完,因此只好把每次讀到的數據先存放到buff中,并判斷每次讀到的數據是否以</teleMedi>結尾,當數據讀取完整了,再復制到sBuffer中提交給程序。
    (5)處理寫就緒事件方法中的主要代碼如下:
    public void send(SelectionKey key)throws IOExceptio{
        ByteBuffer sBuffer=(ByteBuffer)key.attachment();
//獲取需要發送數據的緩沖區
        SocketChannel sChannel=(SocketChannel)key.channel();
        synchronized(sBuffer)
        {        sBuffer.flip();//將緩沖當前的位置值設為
極限,將位置設為0,為下一步復制數據做準備
            sChannel.write(sBuffer);//發送緩沖區中的數據
            sChannel.compact();}//刪除已發送的數據
    (6)當每個緩沖區容量不夠時,需要擴大緩沖區,主要代碼如下:
    protected void resizeBuffer(ByteBuffer bb)
    {  if(bb.remaining()<10){//判斷剩余容量是否
小于10 B
     ByteBuffer bBuffer=ByteBuffer.allocate(bb.capacity()*2);
//容量擴大一倍
     bb.flip();
     bBuffer.put(bb);//把原緩沖區中數據復制到
新緩沖區中
     bb=bBuffer;}}
    鄉村可視化遠程醫療系統中使用Java非阻塞I/O通信技術,可以只使用一個主線程就能實現網絡連接、讀和寫操作,避免了多線程中讀或寫引起的線程阻塞,大幅降低了服務器應用程序的開銷,有效地提高了系統的性能。
參考文獻
[1] 吳易,王凌.Java技術在P2P環境下的應用[J].微計算機信息,2005(3):154-155.
[2] JavaTM Platform Standard Edition 6 API Specification[S]. http://download.oracle.com/javase/6/docs/api/.

此內容為AET網站原創,未經授權禁止轉載。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
亚洲欧美日韩在线播放| 欧美在线播放一区| 亚洲综合精品| 一区二区三区色| 99riav1国产精品视频| 91久久精品www人人做人人爽| 在线观看国产欧美| 有坂深雪在线一区| **网站欧美大片在线观看| 黄色亚洲免费| 一区在线影院| 亚洲福利小视频| 亚洲精品1区2区| 99国产精品久久久久久久久久| 99视频超级精品| 在线亚洲+欧美+日本专区| 亚洲午夜精品视频| 久久久亚洲一区| 亚洲精品一区在线观看香蕉| 亚洲国产视频一区| 亚洲日本黄色| 在线午夜精品| 亚洲欧美日韩久久精品 | 亚洲一二区在线| 亚洲无线视频| 亚洲欧美一区二区原创| 久久国产精品一区二区三区| 亚洲国产高清一区二区三区| 亚洲毛片av在线| 亚洲一级在线| 欧美有码在线观看视频| 久久久国产精品亚洲一区 | 亚洲精品一区在线观看香蕉| 亚洲免费电影在线| 欧美一区二区三区在线观看视频 | 欧美日韩国产成人精品| 欧美日韩在线一区二区| 国产精品夜色7777狼人 | 亚洲精品九九| 这里只有视频精品| 性欧美在线看片a免费观看| 久久激情五月丁香伊人| 欧美成人精品三级在线观看| 欧美先锋影音| 韩国女主播一区二区三区| 亚洲激情女人| 亚洲欧美日韩久久精品| 91久久综合| 午夜欧美大尺度福利影院在线看| 久久久夜夜夜| 欧美揉bbbbb揉bbbbb| 国产精品影片在线观看| 在线观看亚洲精品| 亚洲一区二区不卡免费| 亚洲国产精品久久精品怡红院| 中文日韩欧美| 久久综合九色欧美综合狠狠| 欧美视频免费看| 国产亚洲精品v| 亚洲另类一区二区| 久久精品噜噜噜成人av农村| 中文av一区二区| 老鸭窝毛片一区二区三区| 欧美涩涩网站| 亚洲成色777777在线观看影院| 中文欧美在线视频| 亚洲欧洲一区二区三区久久| 欧美亚洲视频| 欧美日韩视频不卡| 伊人久久大香线蕉综合热线| 亚洲免费视频网站| 99视频一区| 欧美在线免费观看亚洲| 亚洲黄色一区| 午夜精品在线| 欧美精品粉嫩高潮一区二区 | 欧美在线观看一区| 久久免费视频网站| 欧美午夜精彩| 亚洲国产视频直播| 欧美在线一二三| 国模一区二区三区| 亚洲一区一卡| 亚洲国产精品一区二区三区| 亚洲欧美日韩国产| 欧美绝品在线观看成人午夜影视| 国产综合精品| 亚洲主播在线观看| 欧美在线视频一区| 亚洲尤物视频在线| 欧美日本韩国一区| 亚洲高清不卡| 久久精品国语| 久久精品理论片| 欧美成人一区二免费视频软件| 国产精品外国| 正在播放欧美视频| 一本色道久久综合亚洲精品不卡 | 亚洲高清不卡在线| 亚洲国产精品日韩| 翔田千里一区二区| 亚洲精品一线二线三线无人区| 欧美一区二区视频免费观看| 欧美视频免费在线观看| 亚洲精品自在在线观看| 亚洲黑丝在线| 久久天天躁狠狠躁夜夜爽蜜月 | 亚洲视频精品在线| 亚洲视频香蕉人妖| 欧美破处大片在线视频| 亚洲欧洲一区二区三区在线观看| 亚洲国产成人高清精品| 久久综合电影一区| 伊人成年综合电影网| 亚洲国产成人av| 男人的天堂亚洲在线| 亚洲电影免费| 亚洲精品欧美在线| 欧美激情精品久久久久久蜜臀| 亚洲国产成人精品视频| 亚洲另类一区二区| 欧美精品一区二区久久婷婷 | 亚洲一区二区在线播放| 欧美亚洲一区| 国产视频一区三区| 欧美一区二区三区四区在线观看地址 | 欧美成人激情视频| 亚洲国产一区在线| 日韩一级免费| 欧美日韩大陆在线| 日韩小视频在线观看专区| 亚洲午夜久久久久久久久电影院| 欧美手机在线| 亚洲一区二区在线视频 | 国产精品毛片高清在线完整版 | 久久精品99国产精品| 美女脱光内衣内裤视频久久影院 | 亚洲欧美日韩精品久久| 久久久久久亚洲综合影院红桃| 极品尤物久久久av免费看| 亚洲精品日韩精品| 欧美午夜视频一区二区| 亚洲欧美一区二区精品久久久| 久久久免费精品| 亚洲国产成人tv| 亚洲欧美久久久| 国产一区二区三区观看| 亚洲精品国精品久久99热一| 欧美日韩精品一区视频| 亚洲免费视频在线观看| 噜噜爱69成人精品| 一区二区三区 在线观看视频| 久久99伊人| 亚洲日韩欧美一区二区在线| 亚洲一区二区三区视频播放| 国产一区二区三区不卡在线观看| 亚洲精品一区二区三区福利| 欧美午夜精品久久久久久久| 久久av二区| 欧美日韩卡一卡二| 亚洲欧美日本国产有色| 免费成年人欧美视频| 亚洲天堂av高清| 麻豆精品精品国产自在97香蕉| 99精品免费视频| 久久久精品2019中文字幕神马| 精品成人a区在线观看| 亚洲一区二区三区在线| 国内揄拍国内精品少妇国语| 亚洲视屏一区| 狠狠色香婷婷久久亚洲精品| 在线综合亚洲| 狠狠爱成人网| 亚洲欧美国产日韩中文字幕| 樱桃国产成人精品视频| 亚洲欧美日韩精品久久久久| ●精品国产综合乱码久久久久| 午夜欧美视频| 亚洲国产欧美日韩精品| 欧美在线一二三| 亚洲人成久久| 久久综合精品一区| 午夜精品久久久久久久| 欧美日韩伦理在线免费| 亚洲高清不卡av| 国产免费成人av| 中国亚洲黄色| 亚洲福利在线看| 久久久综合香蕉尹人综合网| 一区二区三区精品视频在线观看| 免费一区二区三区| 性一交一乱一区二区洋洋av| 欧美日韩在线精品一区二区三区| 亚洲高清色综合| 国产日韩欧美黄色| 亚洲一区国产| 亚洲日本国产| 欧美成人精品一区| 亚洲高清在线视频| 国产一区二区三区成人欧美日韩在线观看 |