最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 非阻塞I/O使用方法

 更新時(shí)間:2017年09月28日 11:33:40   作者:swt369  
這篇文章主要介紹了Java 非阻塞I/O使用方法,文中涉及非阻塞I/O的簡介,同時(shí)向大家展示了利用非阻塞I/O實(shí)現(xiàn)客戶端的方法,需要的朋友可以參考下。

絕大部分知識(shí)與實(shí)例來自O(shè)'REILLY的《Java網(wǎng)絡(luò)編程》(Java Network Programming,Fourth Edition,by Elliotte Rusty Harold(O'REILLY))。

非阻塞I/O簡介

非阻塞I/O(NIO)是處理高并發(fā)的一種手段。在高并發(fā)的情況下,創(chuàng)建和回收線程以及在線程間切換的開銷變得不容忽視,此時(shí)就可以使用非阻塞I/O技術(shù)。這種技術(shù)的核心思想是每次選取一個(gè)準(zhǔn)備好的連接,盡快地填充這個(gè)連接所能管理的盡可能多的數(shù)據(jù),然后轉(zhuǎn)向下一個(gè)準(zhǔn)備好的連接。

利用非阻塞I/O實(shí)現(xiàn)的客戶端

一般情況下,客戶端不會(huì)需要處理很高數(shù)量的并發(fā)連接。事實(shí)上,非阻塞I/O主要是為服務(wù)器設(shè)計(jì)的,但它也可以用在客戶端上。由于客戶端的設(shè)計(jì)相比服務(wù)器容易,因此下面先用客戶端來進(jìn)行簡單演示。

首先介紹通道(channel)和緩沖區(qū)。非阻塞I/O中使用SocketChannel類創(chuàng)建連接。要獲取SocketChannel對象,需要將一個(gè)SocketAddress對象(通常會(huì)使用它的子類InetSocketAddress)傳入它的靜態(tài)工廠方法open()中。下面為一個(gè)示例:

SocketAddress address = new InetSocketAddress("127.0.0.1", 19);
SocketChannel client = SocketChannel.open(address);

open()方法是阻塞的,因此這之后的代碼在連接建立之前不會(huì)執(zhí)行。如果連接無法建立,會(huì)拋出一個(gè)IOException異常。

連接建立之后就需要獲取輸入和輸出。不同于傳統(tǒng)的getInputStream()與getOutputStream(),利用通道,你可以直接寫入通道本身。不是寫入字節(jié)數(shù)組,而是要寫入一個(gè)ByteBuffer對象。ByteBuffer對象通過ByteBuffer.allocate(int capacity)獲取,capacity為緩沖區(qū)大小,單位為字節(jié):

ByteBuffer buffer = ByteBuffer.allocate(74);

獲得ByteBuffer對象后,將其傳遞給SocketChannel對象的read()方法,SocketChannel對象會(huì)用從Socket讀取的數(shù)據(jù)填充這個(gè)緩沖區(qū)。read()方法返回成功讀取并儲(chǔ)存在緩沖區(qū)中的字節(jié)數(shù)。默認(rèn)情況下,它會(huì)至少讀取一個(gè)字節(jié),或者返回-1指示數(shù)據(jù)結(jié)束,沒有字節(jié)可用時(shí)阻塞。這與InputStream的行為大致相同。但如果設(shè)置成非阻塞模式,沒有字節(jié)可用時(shí)它會(huì)立即返回0,不會(huì)阻塞。

現(xiàn)在假定緩沖區(qū)內(nèi)已經(jīng)有了一些數(shù)據(jù),之后就需要將它們提取出來。可以使用傳統(tǒng)的方式,先將數(shù)據(jù)寫入一個(gè)字節(jié)數(shù)組,之后再寫入一個(gè)輸出流中。這里介紹一種完全基于通道的方法:利用Channels工具類將輸出流封裝到一個(gè)通道中:

WritableByteChannel out = Channels.newChannel(System.out);

上面的代碼將System.out封裝入一個(gè)通道中。這之后就可以進(jìn)行輸出了。ByteBuffer對象在每次輸出之前,需要調(diào)用一下它的flip()方法,使得通道從開頭開始讀。在讀寫完畢后,還需要調(diào)用它的clear()方法,重置緩沖區(qū)的狀態(tài)。下面是進(jìn)行一次數(shù)據(jù)輸出的代碼:

buffer.flip();
out.write(buffer);
buffer.clear();

實(shí)例1:利用非阻塞I/O實(shí)現(xiàn)的CharGenerator(字符生成器)客戶端

服務(wù)器代碼:

public static void createCharGeneratorServer(){
  try(ServerSocket server = new ServerSocket(19)){
    while(true){
      try(Socket connection = server.accept()){
        OutputStream out = connection.getOutputStream();
        int firstPrintableCharacter = 33;
        int numberOfPrintableCharacter = 94;
        int numberOfCharactersPerLine = 72;
        int start = firstPrintableCharacter;
        while(true){
          for(int i = start ;
              i < start + numberOfCharactersPerLine ; i++){
            out.write
            (firstPrintableCharacter + (i - firstPrintableCharacter) % numberOfPrintableCharacter);
          }
          out.write('\r');
          out.write('\n');
          start = firstPrintableCharacter + (start + 1 - firstPrintableCharacter) % numberOfPrintableCharacter;
        }
      }catch (IOException e) {
        e.printStackTrace();
      }
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}

客戶端代碼:

try {
  SocketAddress address = new InetSocketAddress("127.0.0.1", 19);
  SocketChannel client = SocketChannel.open(address);
  ByteBuffer buffer = ByteBuffer.allocate(74);
    WritableByteChannel out = Channels.newChannel(System.out);
  while(client.read(buffer) != -1){
    buffer.flip();
    out.write(buffer);
    buffer.clear();
  }
} catch (IOException e) {
  e.printStackTrace();
}
輸出(無限循環(huán)):
]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF
^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG
_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI
abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
bcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK

啟用非阻塞模式

上面的程序和使用輸入/輸出流的傳統(tǒng)方式并沒有太大差別。不過,可以調(diào)用ServerSocket的configureBlocking(false)方法將其設(shè)置為非阻塞模式。這個(gè)模式下,如果沒有可用的數(shù)據(jù),read()方法會(huì)立即返回,這讓客戶端可以去做其他事情。不過,由于read()方法在讀不到數(shù)據(jù)時(shí)會(huì)返回0,讀取數(shù)據(jù)的循環(huán)需要做一些改動(dòng):

while(true){
  //這里可以寫每次循環(huán)都要做的事,無論有沒有讀到數(shù)據(jù)
  int n = client.read(buffer);
  if(n > 0){
    buffer.flip();
    out.write(buffer);
    buffer.clear();
  }else if (n == -1) {
    //除非服務(wù)器故障,否則不會(huì)發(fā)生
    break;
  }
}

總結(jié)

以上就是本文關(guān)于Java 非阻塞I/O使用方法的全部內(nèi)容,希望對大家有所幫助。歡迎各位參閱:Java網(wǎng)絡(luò)編程基礎(chǔ)篇之單向通信,  Java使用代理進(jìn)行網(wǎng)絡(luò)連接方法示例等,有什么問題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家。感謝大家對本站的支持!

相關(guān)文章

  • Java String.format()的用法

    Java String.format()的用法

    本篇文章主要介紹了JAVA的 String.format()的使用,具有一定的參考價(jià)值,有需要的可以了解一下,希望能夠給你帶來幫助
    2021-11-11
  • Java中String、StringBuffer、StringBuilder的區(qū)別詳解

    Java中String、StringBuffer、StringBuilder的區(qū)別詳解

    java中String、StringBuffer、StringBuilder是編程中經(jīng)常使用的字符串類,他們之間有什么區(qū)別呢?下面小編給大家總結(jié)了Java中String、StringBuffer、StringBuilder的區(qū)別詳解,需要的朋友參考下吧
    2016-06-06
  • java使用spring實(shí)現(xiàn)讀寫分離的示例代碼

    java使用spring實(shí)現(xiàn)讀寫分離的示例代碼

    本篇文章主要介紹了java使用spring實(shí)現(xiàn)讀寫分離的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java服務(wù)端服務(wù)監(jiān)控:Prometheus與Spring Boot Actuator的集成方式

    Java服務(wù)端服務(wù)監(jiān)控:Prometheus與Spring Boot Actuator的集成方式

    本文介紹了如何將Prometheus與SpringBootActuator集成,實(shí)現(xiàn)對Java服務(wù)端應(yīng)用的監(jiān)控,通過集成,可以利用Prometheus的強(qiáng)大監(jiān)控能力,及時(shí)發(fā)現(xiàn)和解決性能問題
    2024-12-12
  • springboot動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)方法示例

    springboot動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)方法示例

    這篇文章主要給大家介紹了關(guān)于springboot動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java語言描述存儲(chǔ)結(jié)構(gòu)與鄰接矩陣代碼示例

    Java語言描述存儲(chǔ)結(jié)構(gòu)與鄰接矩陣代碼示例

    這篇文章主要介紹了Java語言描述存儲(chǔ)結(jié)構(gòu)與鄰接矩陣代碼示例,涉及Java存儲(chǔ)結(jié)構(gòu),鄰接矩陣,鄰接表的介紹與比較,然后分享了鄰接矩陣的Java實(shí)現(xiàn)等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考。
    2017-11-11
  • Java發(fā)送https請求并跳過ssl證書驗(yàn)證方法

    Java發(fā)送https請求并跳過ssl證書驗(yàn)證方法

    最近在負(fù)責(zé)一個(gè)對接第三方服務(wù)的事情,在對接期間因?yàn)榈谌椒?wù)為https的請求,這篇文章主要給大家介紹了關(guān)于Java發(fā)送https請求并跳過ssl證書驗(yàn)證的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 解決mybatis 執(zhí)行mapper的方法時(shí)報(bào)空指針問題

    解決mybatis 執(zhí)行mapper的方法時(shí)報(bào)空指針問題

    這篇文章主要介紹了解決mybatis 執(zhí)行mapper的方法時(shí)報(bào)空指針問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring自定義注解實(shí)現(xiàn)接口版本管理

    Spring自定義注解實(shí)現(xiàn)接口版本管理

    這篇文章主要介紹了Spring自定義注解實(shí)現(xiàn)接口版本管理,RequestMappingHandlerMapping類是與 @RequestMapping相關(guān)的,它定義映射的規(guī)則,即滿足怎樣的條件則映射到那個(gè)接口上,需要的朋友可以參考下
    2023-11-11
  • Java深入淺出說流的使用

    Java深入淺出說流的使用

    這篇文章主要介紹了Java深入淺出說流的使用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09

最新評論

积石山| 河西区| 江孜县| 临沂市| 方正县| 三河市| 榆社县| 静海县| 永年县| 油尖旺区| 惠安县| 漳浦县| 汤原县| 望都县| 凤庆县| 襄城县| 红安县| 商丘市| 荥阳市| 南城县| 江西省| 漳州市| 陇川县| 东台市| 蛟河市| 九寨沟县| 桐乡市| 金川县| 宝清县| 和田县| 太和县| 闵行区| 吉木乃县| 资阳市| 定州市| 广丰县| 小金县| 玛多县| 桐柏县| 长顺县| 碌曲县|