Netty由淺到深_第二章_BIO模型

BIO模型

I/O模型基本說明

  1. Java共支持3中網絡編程I/O模型:BIO,NIO,AIO
  2. java BIO : 同步阻塞(傳統阻塞型),服務器實現模式爲:一個連接對應一個線程,即客戶端有連接請求時,服務器端就需要啓動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷
  3. java NIO : 同步非阻塞。服務器實現模式爲:一個線程處理多個請求(連接),即客戶端發送的請求連接都會註冊到多路複用器上,多路複用器輪詢連接,有I/O請求就行處理
  4. java AIO : 異步非阻塞。AIO引入異步通信概念,採用了Proactor模式,簡化了程序編寫。有效的請求才啓動線程,它的特點是先由操作系統完成讀寫,才通知服務端程序啓動線程去處理,一般適用於連接數較多且持續時間較長的應用

BIO、NIO、AIO適用場景分析

  1. BIO方式適用於連接數目比較小且固定的架構,這種方法對服務器資源要求比較高

Alt

  1. NIO方式適用於連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,彈幕系統,服務器間通訊等

在這裏插入圖片描述

  1. AIO 方式適用於連接數目多且事件較長(重操作)的架構,比如相冊服務器,充分調用OS參與併發操作,編程相對複雜

BIO模型介紹

  1. java BIO 就是傳統的java io編程,其相關類和接口在java.io
  2. BIO(BlockingI/O):同步阻塞,服務器實現模式爲一個連接一個線程,即客戶端有連接請求時服務器端就需要啓動一個線程進行處理,如果這個連接不做任何事情或造成不必要的線程開銷,可以通過線程池機制改善(實現多個客戶端連接服務器)
  3. BIO方式適用於連接數目較小且固定的架構,這種方式對服務器資源要求比較高,併發能力不足
  4. BIO編程簡單流程
    1)服務器端啓動一個ServerSocket
    2)客戶端啓動Socket對服務器進行通信,默認情況下服務器端需要對每個客戶端建立一個線程進行通訊
    3)客戶端發出請求後,先諮詢服務器是否有線程響應,如果沒有則會等待,或者被拒絕
    4)如果有響應,客戶端線程會等待請求結束後,在持續進行
  5. 代碼實戰(線程池版本)
package com.dd.bio;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BIOServer {
    public static void main(String[] args) throws IOException {
        //線程池機制
        //創建一個線程池
        //如果有客戶端連接,就創建一個線程
        ExecutorService executorService = Executors.newCachedThreadPool();
        //創建serverSocket
        ServerSocket serverSocket = new ServerSocket(6666);
        while (true){
            //監聽,等待客戶連接,此步驟會阻塞
            final Socket socket = serverSocket.accept();
            System.out.println("連接到一個客戶端");
            //啓動一個線程與之通信
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    //和客戶端通信
                    handler(socket);
                }
            });
        }

    }

    //編寫一個handler方法,與客戶端通訊
    public static void handler(Socket socket){
        System.out.println("線程信息 id="+Thread.currentThread().getId()+"線程名字+"
                +Thread.currentThread().getName());
        try {
            byte[] bytes = new byte[8*1024];
            //通過socket獲取輸入流
            InputStream inputStream = socket.getInputStream();
            //循環讀取客戶端發送的數據,此地方沒有緩衝流
            while (true){
                //此步驟也會阻塞
                int read = inputStream.read(bytes);
                if (read!=-1){
                    System.out.println(new String(bytes,0,read));
                }else {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

  1. java BIO 問題分析
    1)每個請求都需要創建獨立的線程,與對應的客戶端進行數據Read+業務處理,數據write
    2)當併發數較大時,需要創建大量線程來處理連接,系統資源佔用較大
    3)連接建立後,如果當前線程暫時沒有數據可讀,則線程就阻塞在Read操作上,造成線程資源浪費
親!點擊學習Netty框架,下一篇文章_NIO基本介紹
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章