国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Netty序章之BIO NIO AIO演變

CntChen / 1608人閱讀

摘要:后改良為用線程池的方式代替新增線程,被稱(chēng)為偽異步。最大的問(wèn)題是阻塞,同步。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。這些都會(huì)被注冊(cè)在多路復(fù)用器上。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。并沒(méi)有采用的多路復(fù)用器,而是使用異步通道的概念。

Netty是一個(gè)提供異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用以快速開(kāi)發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶(hù)端程序。Netty簡(jiǎn)化了網(wǎng)絡(luò)程序的開(kāi)發(fā),是很多框架和公司都在使用的技術(shù)。更是面試的加分項(xiàng)。Netty并非橫空出世,它是在BIO,NIO,AIO演變中的產(chǎn)物,是一種NIO框架。而B(niǎo)IO,NIO,AIO更是筆試中要考,面試中要問(wèn)的技術(shù)。也是一個(gè)很好的加分項(xiàng),加分就是加工資,你還在等什么?本章帶你細(xì)細(xì)品味三者的不同!
流程圖:
BIO NIO AIO 流程圖

技術(shù):BIO,NIO,AIO
說(shuō)明:github上有更全的源碼。
源碼:https://github.com/ITDragonBl...

BIO

BIO 全稱(chēng)Block-IO 是一種阻塞同步的通信模式。我們常說(shuō)的Stock IO 一般指的是BIO。是一個(gè)比較傳統(tǒng)的通信方式,模式簡(jiǎn)單,使用方便。但并發(fā)處理能力低,通信耗時(shí),依賴(lài)網(wǎng)速。

BIO 設(shè)計(jì)原理:

服務(wù)器通過(guò)一個(gè)Acceptor線程負(fù)責(zé)監(jiān)聽(tīng)客戶(hù)端請(qǐng)求和為每個(gè)客戶(hù)端創(chuàng)建一個(gè)新的線程進(jìn)行鏈路處理。典型的一請(qǐng)求一應(yīng)答模式。若客戶(hù)端數(shù)量增多,頻繁地創(chuàng)建和銷(xiāo)毀線程會(huì)給服務(wù)器打開(kāi)很大的壓力。后改良為用線程池的方式代替新增線程,被稱(chēng)為偽異步IO。

服務(wù)器提供IP地址和監(jiān)聽(tīng)的端口,客戶(hù)端通過(guò)TCP的三次握手與服務(wù)器連接,連接成功后,雙放才能通過(guò)套接字(Stock)通信。
小結(jié):BIO模型中通過(guò)Socket和ServerSocket完成套接字通道的實(shí)現(xiàn)。阻塞,同步,建立連接耗時(shí)。

BIO服務(wù)器代碼,負(fù)責(zé)啟動(dòng)服務(wù),阻塞服務(wù),監(jiān)聽(tīng)客戶(hù)端請(qǐng)求,新建線程處理任務(wù)。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**

IO 也稱(chēng)為 BIO,Block IO 阻塞同步的通訊方式

比較傳統(tǒng)的技術(shù),實(shí)際開(kāi)發(fā)中基本上用Netty或者是AIO。熟悉BIO,NIO,體會(huì)其中變化的過(guò)程。作為一個(gè)web開(kāi)發(fā)人員,stock通訊面試經(jīng)常問(wèn)題。

BIO最大的問(wèn)題是:阻塞,同步。

BIO通訊方式很依賴(lài)于網(wǎng)絡(luò),若網(wǎng)速不好,阻塞時(shí)間會(huì)很長(zhǎng)。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。

BIO工作流程:

第一步:server端服務(wù)器啟動(dòng)

第二步:server端服務(wù)器阻塞監(jiān)聽(tīng)client請(qǐng)求

第三步:server端服務(wù)器接收請(qǐng)求,創(chuàng)建線程實(shí)現(xiàn)任務(wù)

*/
public class ITDragonBIOServer {

private static final Integer PORT = 8888; // 服務(wù)器對(duì)外的端口號(hào)  
public static void main(String[] args) {  
    ServerSocket server = null;  
    Socket socket = null;  
    ThreadPoolExecutor executor = null;  
    try {  
        server = new ServerSocket(PORT); // ServerSocket 啟動(dòng)監(jiān)聽(tīng)端口  
        System.out.println("BIO Server 服務(wù)器啟動(dòng).........");  
        /*--------------傳統(tǒng)的新增線程處理----------------*/
        /*while (true) { 
            // 服務(wù)器監(jiān)聽(tīng):阻塞,等待Client請(qǐng)求 
            socket = server.accept(); 
            System.out.println("server 服務(wù)器確認(rèn)請(qǐng)求 : " + socket); 
            // 服務(wù)器連接確認(rèn):確認(rèn)Client請(qǐng)求后,創(chuàng)建線程執(zhí)行任務(wù)  。很明顯的問(wèn)題,若每接收一次請(qǐng)求就要?jiǎng)?chuàng)建一個(gè)線程,顯然是不合理的。
            new Thread(new ITDragonBIOServerHandler(socket)).start(); 
        } */
        /*--------------通過(guò)線程池處理緩解高并發(fā)給程序帶來(lái)的壓力(偽異步IO編程)----------------*/  
        executor = new ThreadPoolExecutor(10, 100, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue(50));  
        while (true) {  
            socket = server.accept();  // 服務(wù)器監(jiān)聽(tīng):阻塞,等待Client請(qǐng)求 
            ITDragonBIOServerHandler serverHandler = new ITDragonBIOServerHandler(socket);  
            executor.execute(serverHandler);  
        }  
    } catch (IOException e) {  
        e.printStackTrace();  
    } finally {  
        try {  
            if (null != socket) {  
              socket.close(); 
              socket = null;
            }  
            if (null != server) {  
                server.close();  
                server = null;  
                System.out.println("BIO Server 服務(wù)器關(guān)閉了!!!!");  
            }  
            executor.shutdown();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  

}
BIO服務(wù)端處理任務(wù)代碼,負(fù)責(zé)處理Stock套接字,返回套接字給客戶(hù)端,解耦。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import com.itdragon.util.CalculatorUtil;

public class ITDragonBIOServerHandler implements Runnable{

private Socket socket;
public ITDragonBIOServerHandler(Socket socket) {

  this.socket = socket;  

}
@Override
public void run() {

  BufferedReader reader = null;  
  PrintWriter writer = null;  
  try {  
      reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));  
      writer = new PrintWriter(this.socket.getOutputStream(), true);  
      String body = null;  
      while (true) {  
          body = reader.readLine(); // 若客戶(hù)端用的是 writer.print() 傳值,那readerLine() 是不能獲取值,細(xì)節(jié)  
          if (null == body) {  
              break;  
          }  
          System.out.println("server服務(wù)端接收參數(shù) : " + body);  
          writer.println(body + " = " + CalculatorUtil.cal(body).toString());
      }  
  } catch (IOException e) {  
      e.printStackTrace();  
  } finally {  
      if (null != writer) {  
          writer.close();  
      }  
      try {  
          if (null != reader) {  
              reader.close();  
          }  
          if (null != this.socket) {  
              this.socket.close();  
              this.socket = null;  
          }  
      } catch (IOException e) {  
          e.printStackTrace();  
      }  
  }  

}
}
BIO客戶(hù)端代碼,負(fù)責(zé)啟動(dòng)客戶(hù)端,向服務(wù)器發(fā)送請(qǐng)求,接收服務(wù)器返回的Stock套接字。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Random;
/**

BIO 客戶(hù)端

Socket : 向服務(wù)端發(fā)送連接

PrintWriter : 向服務(wù)端傳遞參數(shù)

BufferedReader : 從服務(wù)端接收參數(shù)

*/
public class ITDragonBIOClient {

private static Integer PORT = 8888;  
private static String IP_ADDRESS = "127.0.0.1";  
public static void main(String[] args) {  
    for (int i = 0; i < 10; i++) {  
        clientReq(i);  
    }  
}  
private static void clientReq(int i) {  
    Socket socket = null;  
    BufferedReader reader = null;  
    PrintWriter writer = null;  
    try {  
        socket = new Socket(IP_ADDRESS, PORT); // Socket 發(fā)起連接操作。連接成功后,雙方通過(guò)輸入和輸出流進(jìn)行同步阻塞式通信  
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 獲取返回內(nèi)容  
        writer = new PrintWriter(socket.getOutputStream(), true);  
        String []operators = {"+","-","*","/"};
        Random random = new Random(System.currentTimeMillis());  
        String expression = random.nextInt(10)+operators[random.nextInt(4)]+(random.nextInt(10)+1);
        writer.println(expression); // 向服務(wù)器端發(fā)送數(shù)據(jù)  
        System.out.println(i + " 客戶(hù)端打印返回?cái)?shù)據(jù) : " + reader.readLine());  
    } catch (Exception e) {  
        e.printStackTrace();  
    } finally {  
        try {  
            if (null != reader) {  
                reader.close();  
            }  
            if (null != socket) {  
                socket.close();  
                socket = null;  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  

}
NIO
NIO 全稱(chēng)New IO,也叫Non-Block IO 是一種非阻塞同步的通信模式。
NIO 設(shè)計(jì)原理:
NIO 相對(duì)于BIO來(lái)說(shuō)一大進(jìn)步。客戶(hù)端和服務(wù)器之間通過(guò)Channel通信。NIO可以在Channel進(jìn)行讀寫(xiě)操作。這些Channel都會(huì)被注冊(cè)在Selector多路復(fù)用器上。Selector通過(guò)一個(gè)線程不停的輪詢(xún)這些Channel。找出已經(jīng)準(zhǔn)備就緒的Channel執(zhí)行IO操作。
NIO 通過(guò)一個(gè)線程輪詢(xún),實(shí)現(xiàn)千萬(wàn)個(gè)客戶(hù)端的請(qǐng)求,這就是非阻塞NIO的特點(diǎn)。
1)緩沖區(qū)Buffer:它是NIO與BIO的一個(gè)重要區(qū)別。BIO是將數(shù)據(jù)直接寫(xiě)入或讀取到Stream對(duì)象中。而NIO的數(shù)據(jù)操作都是在緩沖區(qū)中進(jìn)行的。緩沖區(qū)實(shí)際上是一個(gè)數(shù)組。Buffer最常見(jiàn)的類(lèi)型是ByteBuffer,另外還有CharBuffer,ShortBuffer,IntBuffer,LongBuffer,F(xiàn)loatBuffer,DoubleBuffer。
2)通道Channel:和流不同,通道是雙向的。NIO可以通過(guò)Channel進(jìn)行數(shù)據(jù)的讀,寫(xiě)和同時(shí)讀寫(xiě)操作。通道分為兩大類(lèi):一類(lèi)是網(wǎng)絡(luò)讀寫(xiě)(SelectableChannel),一類(lèi)是用于文件操作(FileChannel),我們使用的SocketChannel和ServerSocketChannel都是SelectableChannel的子類(lèi)。
3)多路復(fù)用器Selector:NIO編程的基礎(chǔ)。多路復(fù)用器提供選擇已經(jīng)就緒的任務(wù)的能力。就是Selector會(huì)不斷地輪詢(xún)注冊(cè)在其上的通道(Channel),如果某個(gè)通道處于就緒狀態(tài),會(huì)被Selector輪詢(xún)出來(lái),然后通過(guò)SelectionKey可以取得就緒的Channel集合,從而進(jìn)行后續(xù)的IO操作。服務(wù)器端只要提供一個(gè)線程負(fù)責(zé)Selector的輪詢(xún),就可以接入成千上萬(wàn)個(gè)客戶(hù)端,這就是JDK NIO庫(kù)的巨大進(jìn)步。

說(shuō)明:這里的代碼只實(shí)現(xiàn)了客戶(hù)端發(fā)送請(qǐng)求,服務(wù)端接收數(shù)據(jù)的功能。其目的是簡(jiǎn)化代碼,方便理解。github源碼中有完整代碼。
小結(jié):NIO模型中通過(guò)SocketChannel和ServerSocketChannel完成套接字通道的實(shí)現(xiàn)。非阻塞/阻塞,同步,避免TCP建立連接使用三次握手帶來(lái)的開(kāi)銷(xiāo)。

NIO服務(wù)器代碼,負(fù)責(zé)開(kāi)啟多路復(fù)用器,打開(kāi)通道,注冊(cè)通道,輪詢(xún)通道,處理通道。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**

NIO 也稱(chēng) New IO, Non-Block IO,非阻塞同步通信方式

從BIO的阻塞到NIO的非阻塞,這是一大進(jìn)步。功歸于Buffer,Channel,Selector三個(gè)設(shè)計(jì)實(shí)現(xiàn)。

Buffer : 緩沖區(qū)。NIO的數(shù)據(jù)操作都是在緩沖區(qū)中進(jìn)行。緩沖區(qū)實(shí)際上是一個(gè)數(shù)組。而B(niǎo)IO是將數(shù)據(jù)直接寫(xiě)入或讀取到Stream對(duì)象。

Channel : 通道。NIO可以通過(guò)Channel進(jìn)行數(shù)據(jù)的讀,寫(xiě)和同時(shí)讀寫(xiě)操作。

Selector : 多路復(fù)用器。NIO編程的基礎(chǔ)。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。

客戶(hù)端和服務(wù)器通過(guò)Channel連接,而這些Channel都要注冊(cè)在Selector。Selector通過(guò)一個(gè)線程不停的輪詢(xún)這些Channel。找出已經(jīng)準(zhǔn)備就緒的Channel執(zhí)行IO操作。

NIO通過(guò)一個(gè)線程輪詢(xún),實(shí)現(xiàn)千萬(wàn)個(gè)客戶(hù)端的請(qǐng)求,這就是非阻塞NIO的特點(diǎn)。

*/
public class ITDragonNIOServer implements Runnable{

private final int BUFFER_SIZE = 1024; // 緩沖區(qū)大小
private final int PORT = 8888; // 監(jiān)聽(tīng)的端口
private Selector selector; // 多路復(fù)用器,NIO編程的基礎(chǔ),負(fù)責(zé)管理通道Channel
private ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE); // 緩沖區(qū)Buffer
public ITDragonNIOServer() {

  startServer();  

}
private void startServer() {

  try {  
      // 1.開(kāi)啟多路復(fù)用器  
      selector = Selector.open();  
      // 2.打開(kāi)服務(wù)器通道(網(wǎng)絡(luò)讀寫(xiě)通道)  
      ServerSocketChannel channel = ServerSocketChannel.open();  
      // 3.設(shè)置服務(wù)器通道為非阻塞模式,true為阻塞,false為非阻塞  
      channel.configureBlocking(false);  
      // 4.綁定端口  
      channel.socket().bind(new InetSocketAddress(PORT));  
      // 5.把通道注冊(cè)到多路復(fù)用器上,并監(jiān)聽(tīng)阻塞事件  
      /** 
       * SelectionKey.OP_READ     : 表示關(guān)注讀數(shù)據(jù)就緒事件  
       * SelectionKey.OP_WRITE     : 表示關(guān)注寫(xiě)數(shù)據(jù)就緒事件  
       * SelectionKey.OP_CONNECT: 表示關(guān)注socket channel的連接完成事件  
       * SelectionKey.OP_ACCEPT : 表示關(guān)注server-socket channel的accept事件  
       */  
      channel.register(selector, SelectionKey.OP_ACCEPT);  
      System.out.println("Server start >>>>>>>>> port :" + PORT);  
  } catch (IOException e) {  
      e.printStackTrace();  
  }  

}
// 需要一個(gè)線程負(fù)責(zé)Selector的輪詢(xún)
@Override
public void run() {

  while (true) {  
      try {  
          /** 
           * a.select() 阻塞到至少有一個(gè)通道在你注冊(cè)的事件上就緒  
           * b.select(long timeOut) 阻塞到至少有一個(gè)通道在你注冊(cè)的事件上就緒或者超時(shí)timeOut 
           * c.selectNow() 立即返回。如果沒(méi)有就緒的通道則返回0  
           * select方法的返回值表示就緒通道的個(gè)數(shù)。 
           */  
          // 1.多路復(fù)用器監(jiān)聽(tīng)阻塞  
          selector.select();  
          // 2.多路復(fù)用器已經(jīng)選擇的結(jié)果集  
          Iterator selectionKeys = selector.selectedKeys().iterator();  
          // 3.不停的輪詢(xún)  
          while (selectionKeys.hasNext()) {  
              // 4.獲取一個(gè)選中的key  
              SelectionKey key = selectionKeys.next();  
              // 5.獲取后便將其從容器中移除  
              selectionKeys.remove();  
              // 6.只獲取有效的key  
              if (!key.isValid()){  
                  continue;  
              }  
              // 阻塞狀態(tài)處理  
              if (key.isAcceptable()){  
                  accept(key);  
              }  
              // 可讀狀態(tài)處理  
              if (key.isReadable()){  
                  read(key);  
              }  
          }  
      } catch (IOException e) {  
          e.printStackTrace();  
      }  
  }  

}
// 設(shè)置阻塞,等待Client請(qǐng)求。在傳統(tǒng)IO編程中,用的是ServerSocket和Socket。在NIO中采用的ServerSocketChannel和SocketChannel
private void accept(SelectionKey selectionKey) {

  try {  
      // 1.獲取通道服務(wù)  
      ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();  
      // 2.執(zhí)行阻塞方法  
      SocketChannel socketChannel = serverSocketChannel.accept();  
      // 3.設(shè)置服務(wù)器通道為非阻塞模式,true為阻塞,false為非阻塞  
      socketChannel.configureBlocking(false);  
      // 4.把通道注冊(cè)到多路復(fù)用器上,并設(shè)置讀取標(biāo)識(shí)  
      socketChannel.register(selector, SelectionKey.OP_READ);  
  } catch (IOException e) {  
      e.printStackTrace();  
  }  

}
private void read(SelectionKey selectionKey) {

  try {  
      // 1.清空緩沖區(qū)數(shù)據(jù)  
      readBuffer.clear();  
      // 2.獲取在多路復(fù)用器上注冊(cè)的通道  
      SocketChannel socketChannel = (SocketChannel) selectionKey.channel();  
      // 3.讀取數(shù)據(jù),返回  
      int count = socketChannel.read(readBuffer);  
      // 4.返回內(nèi)容為-1 表示沒(méi)有數(shù)據(jù)  
      if (-1 == count) {  
          selectionKey.channel().close();  
          selectionKey.cancel();  
          return ;  
      }  
      // 5.有數(shù)據(jù)則在讀取數(shù)據(jù)前進(jìn)行復(fù)位操作  
      readBuffer.flip();  
      // 6.根據(jù)緩沖區(qū)大小創(chuàng)建一個(gè)相應(yīng)大小的bytes數(shù)組,用來(lái)獲取值  
      byte[] bytes = new byte[readBuffer.remaining()];  
      // 7.接收緩沖區(qū)數(shù)據(jù)  
      readBuffer.get(bytes);  
      // 8.打印獲取到的數(shù)據(jù)  
      System.out.println("NIO Server : " + new String(bytes)); // 不能用bytes.toString()  
  } catch (IOException e) {  
      e.printStackTrace();  
  }  

}
public static void main(String[] args) {

  new Thread(new ITDragonNIOServer()).start();  

}
}
NIO客戶(hù)端代碼,負(fù)責(zé)連接服務(wù)器,聲明通道,連接通道

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class ITDragonNIOClient {

private final static int PORT = 8888;  
private final static int BUFFER_SIZE = 1024;  
private final static String IP_ADDRESS = "127.0.0.1";  
public static void main(String[] args) {  
    clientReq();
}  
private static void clientReq() {
    // 1.創(chuàng)建連接地址  
    InetSocketAddress inetSocketAddress = new InetSocketAddress(IP_ADDRESS, PORT);  
    // 2.聲明一個(gè)連接通道  
    SocketChannel socketChannel = null;  
    // 3.創(chuàng)建一個(gè)緩沖區(qū)  
    ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);  
    try {  
        // 4.打開(kāi)通道  
        socketChannel = SocketChannel.open();  
        // 5.連接服務(wù)器  
        socketChannel.connect(inetSocketAddress);  
        while(true){  
            // 6.定義一個(gè)字節(jié)數(shù)組,然后使用系統(tǒng)錄入功能:  
            byte[] bytes = new byte[BUFFER_SIZE];  
            // 7.鍵盤(pán)輸入數(shù)據(jù)  
            System.in.read(bytes);  
            // 8.把數(shù)據(jù)放到緩沖區(qū)中  
            byteBuffer.put(bytes);  
            // 9.對(duì)緩沖區(qū)進(jìn)行復(fù)位  
            byteBuffer.flip();  
            // 10.寫(xiě)出數(shù)據(jù)  
            socketChannel.write(byteBuffer);  
            // 11.清空緩沖區(qū)數(shù)據(jù)  
            byteBuffer.clear();  
        }  
    } catch (IOException e) {  
        e.printStackTrace();  
    } finally {  
        if (null != socketChannel) {  
            try {  
                socketChannel.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    } 
}

}
AIO
AIO 也叫NIO2.0 是一種非阻塞異步的通信模式。在NIO的基礎(chǔ)上引入了新的異步通道的概念,并提供了異步文件通道和異步套接字通道的實(shí)現(xiàn)。
AIO 并沒(méi)有采用NIO的多路復(fù)用器,而是使用異步通道的概念。其read,write方法的返回類(lèi)型都是Future對(duì)象。而Future模型是異步的,其核心思想是:去主函數(shù)等待時(shí)間。

小結(jié):AIO模型中通過(guò)AsynchronousSocketChannel和AsynchronousServerSocketChannel完成套接字通道的實(shí)現(xiàn)。非阻塞,異步。

AIO服務(wù)端代碼,負(fù)責(zé)創(chuàng)建服務(wù)器通道,綁定端口,等待請(qǐng)求。

import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**

AIO, 也叫 NIO2.0 是一種異步非阻塞的通信方式

AIO 引入了異步通道的概念 AsynchronousServerSocketChannel和AsynchronousSocketChannel 其read和write方法返回值類(lèi)型是Future對(duì)象。

*/
public class ITDragonAIOServer {

  
private ExecutorService executorService;          // 線程池
private AsynchronousChannelGroup threadGroup;      // 通道組
public AsynchronousServerSocketChannel asynServerSocketChannel;  // 服務(wù)器通道 
public void start(Integer port){  
    try {  
        // 1.創(chuàng)建一個(gè)緩存池  
        executorService = Executors.newCachedThreadPool();  
        // 2.創(chuàng)建通道組  
        threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);  
        // 3.創(chuàng)建服務(wù)器通道  
        asynServerSocketChannel = AsynchronousServerSocketChannel.open(threadGroup);  
        // 4.進(jìn)行綁定  
        asynServerSocketChannel.bind(new InetSocketAddress(port));  
        System.out.println("server start , port : " + port);  
        // 5.等待客戶(hù)端請(qǐng)求  
        asynServerSocketChannel.accept(this, new ITDragonAIOServerHandler());  
        // 一直阻塞 不讓服務(wù)器停止,真實(shí)環(huán)境是在tomcat下運(yùn)行,所以不需要這行代碼  
        Thread.sleep(Integer.MAX_VALUE);  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}  
public static void main(String[] args) {  
    ITDragonAIOServer server = new ITDragonAIOServer();  
    server.start(8888);  
}  

}
AIO服務(wù)器任務(wù)處理代碼,負(fù)責(zé),讀取數(shù)據(jù),寫(xiě)入數(shù)據(jù)

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;
import com.itdragon.util.CalculatorUtil;

public class ITDragonAIOServerHandler implements CompletionHandler {
private final Integer BUFFER_SIZE = 1024;
@Override
public void completed(AsynchronousSocketChannel asynSocketChannel, ITDragonAIOServer attachment) {

  // 保證多個(gè)客戶(hù)端都可以阻塞  
  attachment.asynServerSocketChannel.accept(attachment, this);  
  read(asynSocketChannel);  

}
//讀取數(shù)據(jù)
private void read(final AsynchronousSocketChannel asynSocketChannel) {

  ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);  
  asynSocketChannel.read(byteBuffer, byteBuffer, new CompletionHandler() {  
      @Override  
      public void completed(Integer resultSize, ByteBuffer attachment) {  
          //進(jìn)行讀取之后,重置標(biāo)識(shí)位  
          attachment.flip();  
          //獲取讀取的數(shù)據(jù)  
          String resultData = new String(attachment.array()).trim();  
          System.out.println("Server -> " + "收到客戶(hù)端的數(shù)據(jù)信息為:" + resultData);  
          String response = resultData + " = " + CalculatorUtil.cal(resultData);  
          write(asynSocketChannel, response);  
      }  
      @Override  
      public void failed(Throwable exc, ByteBuffer attachment) {  
          exc.printStackTrace();  
      }  
  });  

}
// 寫(xiě)入數(shù)據(jù)
private void write(AsynchronousSocketChannel asynSocketChannel, String response) {

  try {  
      // 把數(shù)據(jù)寫(xiě)入到緩沖區(qū)中  
      ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);  
      buf.put(response.getBytes());  
      buf.flip();  
      // 在從緩沖區(qū)寫(xiě)入到通道中  
      asynSocketChannel.write(buf).get();  
  } catch (InterruptedException e) {  
      e.printStackTrace();  
  } catch (ExecutionException e) {  
      e.printStackTrace();  
  }  

}
@Override
public void failed(Throwable exc, ITDragonAIOServer attachment) {

  exc.printStackTrace();  

}
}
AIO客戶(hù)端代碼,負(fù)責(zé)連接服務(wù)器,聲明通道,連接通道

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.Random;

public class ITDragonAIOClient implements Runnable{

private static Integer PORT = 8888;  
private static String IP_ADDRESS = "127.0.0.1";
private AsynchronousSocketChannel asynSocketChannel ;  
public ITDragonAIOClient() throws Exception {  
    asynSocketChannel = AsynchronousSocketChannel.open();  // 打開(kāi)通道  
}  
public void connect(){  
    asynSocketChannel.connect(new InetSocketAddress(IP_ADDRESS, PORT));  // 創(chuàng)建連接 和NIO一樣  
}  
public void write(String request){  
    try {  
        asynSocketChannel.write(ByteBuffer.wrap(request.getBytes())).get();  
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);  
        asynSocketChannel.read(byteBuffer).get();  
        byteBuffer.flip();  
        byte[] respByte = new byte[byteBuffer.remaining()];  
        byteBuffer.get(respByte); // 將緩沖區(qū)的數(shù)據(jù)放入到 byte數(shù)組中  
        System.out.println(new String(respByte,"utf-8").trim());  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}  
@Override  
public void run() {  
    while(true){  
    }  
}  
public static void main(String[] args) throws Exception {  
    for (int i = 0; i < 10; i++) {
        ITDragonAIOClient myClient = new ITDragonAIOClient();  
        myClient.connect();  
        new Thread(myClient, "myClient").start(); 
        String []operators = {"+","-","*","/"};
        Random random = new Random(System.currentTimeMillis());  
        String expression = random.nextInt(10)+operators[random.nextInt(4)]+(random.nextInt(10)+1);
        myClient.write(expression);  
    }
}  

}
常見(jiàn)面試題
1 IO,NIO,AIO區(qū)別
IO 阻塞同步通信模式,客戶(hù)端和服務(wù)器連接需要三次握手,使用簡(jiǎn)單,但吞吐量小
NIO 非阻塞同步通信模式,客戶(hù)端與服務(wù)器通過(guò)Channel連接,采用多路復(fù)用器輪詢(xún)注冊(cè)的Channel。提高吞吐量和可靠性。
AIO 非阻塞異步通信模式,NIO的升級(jí)版,采用異步通道實(shí)現(xiàn)異步通信,其read和write方法均是異步方法。

2 Stock通信的偽代碼實(shí)現(xiàn)流程
服務(wù)器綁定端口:server = new ServerSocket(PORT)
服務(wù)器阻塞監(jiān)聽(tīng):socket = server.accept()
服務(wù)器開(kāi)啟線程:new Thread(Handle handle)
服務(wù)器讀寫(xiě)數(shù)據(jù):BufferedReader PrintWriter
客戶(hù)端綁定IP和PORT:new Socket(IP_ADDRESS, PORT)
客戶(hù)端傳輸接收數(shù)據(jù):BufferedReader PrintWriter

3 TCP協(xié)議與UDP協(xié)議有什么區(qū)別
TCP : 傳輸控制協(xié)議是基于連接的協(xié)議,在正式收發(fā)數(shù)據(jù)前,必須和對(duì)方建立可靠的連接。速度慢,合適傳輸大量數(shù)據(jù)。
UDP : 用戶(hù)數(shù)據(jù)報(bào)協(xié)議是與TCP相對(duì)應(yīng)的協(xié)議。面向非連接的協(xié)議,不與對(duì)方建立連接,而是直接就把數(shù)據(jù)包發(fā)送過(guò)去,速度快,適合傳輸少量數(shù)據(jù)。

4 什么是同步阻塞BIO,同步非阻塞NIO,異步非阻塞AIO
同步阻塞IO : 用戶(hù)進(jìn)程發(fā)起一個(gè)IO操作以后,必須等待IO操作的真正完成后,才能繼續(xù)運(yùn)行。
同步非阻塞IO: 用戶(hù)進(jìn)程發(fā)起一個(gè)IO操作以后,可做其它事情,但用戶(hù)進(jìn)程需要經(jīng)常詢(xún)問(wèn)IO操作是否完成,這樣造成不必要的CPU資源浪費(fèi)。
異步非阻塞IO: 用戶(hù)進(jìn)程發(fā)起一個(gè)IO操作然后,立即返回,等IO操作真正的完成以后,應(yīng)用程序會(huì)得到IO操作完成的通知。類(lèi)比Future模式。

總結(jié)
1 BIO模型中通過(guò)Socket和ServerSocket完成套接字通道實(shí)現(xiàn)。阻塞,同步,連接耗時(shí)。
2 NIO模型中通過(guò)SocketChannel和ServerSocketChannel完成套接字通道實(shí)現(xiàn)。非阻塞/阻塞,同步,避免TCP建立連接使用三次握手帶來(lái)的開(kāi)銷(xiāo)。
3 AIO模型中通過(guò)AsynchronousSocketChannel和AsynchronousServerSocketChannel完成套接字通道實(shí)現(xiàn)。非阻塞,異步。
BIO NIO AIO 對(duì)比

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/101961.html

相關(guān)文章

  • Netty章之BIO NIO AIO演變

    摘要:后改良為用線程池的方式代替新增線程,被稱(chēng)為偽異步。最大的問(wèn)題是阻塞,同步。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。這些都會(huì)被注冊(cè)在多路復(fù)用器上。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。并沒(méi)有采用的多路復(fù)用器,而是使用異步通道的概念。 Netty是一個(gè)提供異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用以快速開(kāi)發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶(hù)端程序。Netty簡(jiǎn)化了網(wǎng)絡(luò)程序的開(kāi)發(fā),是很多框架和公司...

    VincentFF 評(píng)論0 收藏0
  • BIOAIO模型在JDK實(shí)現(xiàn),Netty序章

    摘要:當(dāng)操作系統(tǒng)發(fā)生事件,并且準(zhǔn)備好數(shù)據(jù)后,在主動(dòng)通知應(yīng)用程序,觸發(fā)相應(yīng)的函數(shù)。當(dāng)失敗時(shí)觸發(fā)該方法,第一個(gè)參數(shù)代表操作失敗引發(fā)的異常或錯(cuò)誤。 BIO編程 回顧下Linux下阻塞IO模型: showImg(https://segmentfault.com/img/bVbtFcN?w=826&h=471); 再看看Java的BIO編程模型: showImg(https://segmentfaul...

    draveness 評(píng)論0 收藏0
  • java-netty-Netty in Action 5th-ch1-Netty and Java

    摘要:一個(gè)多路復(fù)用器可以負(fù)責(zé)成千上萬(wàn)的通道,沒(méi)有上限。不需要通過(guò)對(duì)多路復(fù)用器對(duì)注冊(cè)的通道進(jìn)行輪詢(xún)操作即可實(shí)現(xiàn)異步讀寫(xiě),從而簡(jiǎn)化編程模型。同時(shí),支持支持如果是怎么辦最后,到目前位置,支持不支持二無(wú)法擴(kuò)展作為的核心,無(wú)法擴(kuò)展,私有構(gòu)造函數(shù)。 前言 netty 學(xué)習(xí) 基于 netty in action 5th, 官網(wǎng)資料,網(wǎng)絡(luò)博客等 1.1 Why Netty? netty 是一個(gè)中間層的抽象 ...

    LeviDing 評(píng)論0 收藏0
  • JDK中關(guān)于BIONIOAIO,同步,異步介紹

    摘要:即可以理解為,方法都是異步的,完成后會(huì)主動(dòng)調(diào)用回調(diào)函數(shù)。主要在包下增加了下面四個(gè)異步通道其中的方法,會(huì)返回一個(gè)帶回調(diào)函數(shù)的對(duì)象,當(dāng)執(zhí)行完讀取寫(xiě)入操作后,直接調(diào)用回調(diào)函數(shù)。 本文原創(chuàng)地址,我的博客:jsbintask.cn/2019/04/16/…(食用效果最佳),轉(zhuǎn)載請(qǐng)注明出處! 在理解什么是BIO,NIO,AIO之前,我們首先需要了解什么是同步,異步,阻塞,非阻塞。假如我們現(xiàn)在要去銀行取...

    opengps 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<