日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里面试题BIO和NIO数量问题附答案和代码

發(fā)布時間:2025/3/11 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里面试题BIO和NIO数量问题附答案和代码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、問題

BIO 和 NIO 作為 Server 端,當(dāng)建立了 10 個連接時,分別產(chǎn)生多少個線程?

答案: 因為傳統(tǒng)的 IO 也就是 BIO 是同步線程堵塞的,所以每個連接都要分配一個專用線程來處理請求,這樣 10 個連接就會創(chuàng)建 10 個線程去處理。而 NIO 是一種同步非阻塞的 I/O 模型,它的核心技術(shù)是多路復(fù)用,可以使用一個鏈接上的不同通道來處理不同的請求,所以即使有 10 個連接,對于 NIO 來說,開啟 1 個線程就夠了。

二、BIO 代碼實現(xiàn)

public class DemoServer extends Thread {private ServerSocket serverSocket;public int getPort() {return serverSocket.getLocalPort();}public void run() {try {serverSocket = new ServerSocket(0);while (true) {Socket socket = serverSocket.accept();RequestHandler requestHandler = new RequestHandler(socket);requestHandler.start();}} catch (IOException e) {e.printStackTrace();} finally {if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}public static void main(String[] args) throws IOException {DemoServer server = new DemoServer();server.start();try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));bufferedReader.lines().forEach(s -> System.out.println(s));}}} // 簡化實現(xiàn),不做讀取,直接發(fā)送字符串 class RequestHandler extends Thread {private Socket socket;RequestHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {out.println("Hello world!");out.flush();} catch (Exception e) {e.printStackTrace();}}}
  • 服務(wù)器端啟動 ServerSocket,端口 0 表示自動綁定一個空閑端口。
  • 調(diào)用 accept 方法,阻塞等待客戶端連接。
  • 利用 Socket 模擬了一個簡單的客戶端,只進行連接、讀取、打印。
  • 當(dāng)連接建立后,啟動一個單獨線程負(fù)責(zé)回復(fù)客戶端請求。

這樣,一個簡單的 Socket 服務(wù)器就被實現(xiàn)出來了。

(圖片來源于楊曉峰)

三、NIO 代碼實現(xiàn)

public class NIOServer extends Thread {public void run() {try (Selector selector = Selector.open();ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 創(chuàng)建 Selector 和 ChannelserverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));serverSocket.configureBlocking(false);// 注冊到 Selector,并說明關(guān)注點serverSocket.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();// 阻塞等待就緒的 Channel,這是關(guān)鍵點之一Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iter = selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();// 生產(chǎn)系統(tǒng)中一般會額外進行就緒狀態(tài)檢查sayHelloWorld((ServerSocketChannel) key.channel());iter.remove();}}} catch (IOException e) {e.printStackTrace();}}private void sayHelloWorld(ServerSocketChannel server) throws IOException {try (SocketChannel client = server.accept();) { client.write(Charset.defaultCharset().encode("Hello world!"));}}// 省略了與前面類似的 main }
  • 首先,通過 Selector.open() 創(chuàng)建一個 Selector,作為類似調(diào)度員的角色。
  • 然后,創(chuàng)建一個 ServerSocketChannel,并且向 Selector 注冊,通過指定 SelectionKey.OP_ACCEPT,告訴調(diào)度員,它關(guān)注的是新的連接請求。注意:為什么我們要明確配置非阻塞模式呢?這是因為阻塞模式下,注冊操作是不允許的,會拋出 IllegalBlockingModeException 異常。
  • Selector 阻塞在 select 操作,當(dāng)有 Channel 發(fā)生接入請求,就會被喚醒。
  • 在 sayHelloWorld 方法中,通過 SocketChannel 和 Buffer 進行數(shù)據(jù)操作,在本例中是發(fā)送了一段字符串。

可以看到,在前面兩個樣例中,IO 都是同步阻塞模式,所以需要多線程以實現(xiàn)多任務(wù)處理。而 NIO 則是利用了單線程輪詢事件的機制,通過高效地定位就緒的 Channel,來決定做什么,僅僅 select 階段是阻塞的,可以有效避免大量客戶端連接時,頻繁線程切換帶來的問題,應(yīng)用的擴展能力有了非常大的提高。下面這張圖對這種實現(xiàn)思路進行了形象地說明。

(圖片來源于楊曉峰)

四、參考資料

Java核心36講

近期熱門文章

Java 最常見的 200+ 面試題

如果你喜歡本文,掃描二維碼關(guān)注微信公眾號「王磊的博客」

總結(jié)

以上是生活随笔為你收集整理的阿里面试题BIO和NIO数量问题附答案和代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。