三分鐘看Netty (2) 何爲IO多路複用

粗暴的解釋程序員

從JDK 1.0開始,用戶就能夠經過Socket進行網絡編程。在JDK 1.4後,又提供了一種全新的編程方式。編程

在翻閱文檔的時候,相信很多人對「多路複用」這個詞感到陌生和費解。服務器

對於程序員來講,代碼是更容易理解。網絡

BIO示例:多線程

ExecutorService executor = Excutors.newFixedThreadPollExecutor(100);//創建線程池
 ServerSocket serverSocket = new ServerSocket();//新建Socket
 serverSocket.bind(8088);//監聽8088端口

 while(!Thread.currentThread.isInturrupted()){ 
           Socket socket = serverSocket.accept();//循環等待新鏈接進入
           executor.submit(new ConnectIOnHandler(socket));//放入線程池中處理讀寫任務
}


class ConnectIOnHandler extends Thread{
    private Socket socket;
    public ConnectIOnHandler(Socket socket){
       this.socket = socket;
    }
    public void run(){
      while(!Thread.currentThread.isInturrupted()&&!socket.isClosed()){  
          String someThing = socket.read();//讀取對方發來的消息
          if(someThing!=null){
            //TODO 作業務處理
             socket.write();//返回結果
          }
      }
    }
}

NIO 示例:併發

class IoThread extends Thread{
  public void run(){
Set<SelectionKey> selectedKeys=  selector.selectedKeys();
//循環獲取網絡事件。
  Iterator<SelectionKey> i = selectedKeys.iterator();
       for (;;) {
           final SelectionKey k = i.next();
           final Object a = k.attachment();
           i.remove();

           if (a instanceof AbstractNioChannel) {
               processSelectedKey(k, (AbstractNioChannel) a);
           }
}

代碼分析socket

在OIO中,將新鏈接放入到線程池中,利用多線程處理實際的讀寫任務。其中Socket的accept、read、write皆爲阻塞操做。能夠簡單的認爲每個Socket鏈接對應了操做系統的一個小文件,對Socket的讀寫就是對這個文件的讀寫。這是一路一線程,或者是多路一線程的概念。性能

而在NIO中,經過Selector將Channel和event統一管理了起來。一次selector操做能夠獲取一個或者多個網絡鏈接中的讀寫事件。這即是是多路複用的由來,它能夠同時對多個網絡鏈接進行操做this

爲什麼引入NIO操作系統

在OIO編程模式中,經過線程池的引入,解決了OIO阻塞而引起的並行效率問題。看似已經美好,可是互聯網的發展和用戶量的提高,這種古老的編程模式遭受了挑戰。

在OIO中,很難提高併發量。每個新鏈接都須要一個Socket對象,雖然共用了線程池,可是爲了保證響應性,須要設置較大的線程數。因爲線程資源自己昂貴,過量的線程又會致使CPU資源競爭激烈,下降服務性能。OIO的特性決定了它必然沒法支撐較大的併發量。

在NIO中,經過多路複用機制,解決了須要很是多的線程專一IO讀寫的問題,下降了服務的負載。從而提高了服務器的併發量。

多路複用使得服務的併發性上升了一個臺階,進一步的提高還有一個挑戰。下一章將對此進行詳細闡述。

相關文章
相關標籤/搜索