摘要:組件主要有三大核心部分通道,緩沖區(qū)選擇器。選擇區(qū)用于監(jiān)聽多個(gè)通道的事件比如連接打開,數(shù)據(jù)到達(dá)。即用選擇器,借助單一線程,就可對(duì)數(shù)量龐大的活動(dòng)通道實(shí)施監(jiān)控和維護(hù)。
Java NIO 簡(jiǎn)介
JAVA NIO有兩種解釋:一種叫非阻塞IO(Non-blocking I/O),另一種也叫新的IO(New I/O),其實(shí)是同一個(gè)概念。它是一種同步非阻塞的I/O模型,也是I/O多路復(fù)用的基礎(chǔ),已經(jīng)被越來越多地應(yīng)用到大型應(yīng)用服務(wù)器,成為解決高并發(fā)與大量連接、I/O處理問題的有效方式。
NIO是一種基于通道和緩沖區(qū)的I/O方式,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存(區(qū)別于JVM的運(yùn)行時(shí)數(shù)據(jù)區(qū)),然后通過一個(gè)存儲(chǔ)在java堆里面的DirectByteBuffer對(duì)象作為這塊內(nèi)存的直接引用進(jìn)行操作。這樣能在一些場(chǎng)景顯著提高性能,因?yàn)楸苊饬嗽贘ava堆和Native堆中來回復(fù)制數(shù)據(jù)。
Java NIO組件
NIO主要有三大核心部分:Channel(通道),Buffer(緩沖區(qū)), Selector(選擇器)。傳統(tǒng)IO是基于字節(jié)流和字符流進(jìn)行操作(基于流),而NIO基于Channel和Buffer(緩沖區(qū))進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。Selector(選擇區(qū))用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。
Buffer
Buffer(緩沖區(qū))是一個(gè)用于存儲(chǔ)特定基本類型數(shù)據(jù)的容器。除了boolean外,其余每種基本類型都有一個(gè)對(duì)應(yīng)的buffer類。Buffer類的子類有ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer 。
Channel
Channel(通道)表示到實(shí)體,如硬件設(shè)備、文件、網(wǎng)絡(luò)套接字或可以執(zhí)行一個(gè)或多個(gè)不同 I/O 操作(如讀取或?qū)懭耄┑某绦蚪M件的開放的連接。Channel接口的常用實(shí)現(xiàn)類有FileChannel(對(duì)應(yīng)文件IO)、DatagramChannel(對(duì)應(yīng)UDP)、SocketChannel和ServerSocketChannel(對(duì)應(yīng)TCP的客戶端和服務(wù)器端)。Channel和IO中的Stream(流)是差不多一個(gè)等級(jí)的。只不過Stream是單向的,譬如:InputStream, OutputStream.而Channel是雙向的,既可以用來進(jìn)行讀操作,又可以用來進(jìn)行寫操作。
Selector
Selector(選擇器)用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)的線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。即用選擇器,借助單一線程,就可對(duì)數(shù)量龐大的活動(dòng)I/O通道實(shí)施監(jiān)控和維護(hù)。
Java NIO的簡(jiǎn)單實(shí)現(xiàn)
public class Demo1 { private static Integer port = 8080; // 通道管理器(Selector) private static Selector selector; private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS, new LinkedTransferQueue<>(), new ThreadPoolExecutor.AbortPolicy()); public static void main(String[] args) { try { // 創(chuàng)建通道ServerSocketChannel ServerSocketChannel open = ServerSocketChannel.open(); // 將通道設(shè)置為非阻塞 open.configureBlocking(false); // 綁定到指定的端口上 open.bind(new InetSocketAddress(port)); // 通道管理器(Selector) selector = Selector.open(); /** * 將通道(Channel)注冊(cè)到通道管理器(Selector),并為該通道注冊(cè)selectionKey.OP_ACCEPT事件 * 注冊(cè)該事件后,當(dāng)事件到達(dá)的時(shí)候,selector.select()會(huì)返回, * 如果事件沒有到達(dá)selector.select()會(huì)一直阻塞。 */ open.register(selector, SelectionKey.OP_ACCEPT); // 循環(huán)處理 while (true) { /** * 當(dāng)注冊(cè)事件到達(dá)時(shí),方法返回,否則該方法會(huì)一直阻塞 * 該Selector的select()方法將會(huì)返回大于0的整數(shù),該整數(shù)值就表示該Selector上有多少個(gè)Channel具有可用的IO操作 */ int select = selector.select(); System.out.println("當(dāng)前有 " + select + " 個(gè)channel可以操作"); // 一個(gè)SelectionKey對(duì)應(yīng)一個(gè)就緒的通道 SetselectionKeys = selector.selectedKeys(); Iterator iterator = selectionKeys.iterator(); while (iterator.hasNext()) { // 獲取事件 SelectionKey key = iterator.next(); // 移除事件,避免重復(fù)處理 iterator.remove(); // 客戶端請(qǐng)求連接事件,接受客戶端連接就緒 if (key.isAcceptable()) { accept(key); } else if (key.isReadable()) { // 監(jiān)聽到讀事件,對(duì)讀事件進(jìn)行處理 threadPoolExecutor.submit(new NioServerHandler(key)); } } } } catch (IOException e) { e.printStackTrace(); } } /** * 處理客戶端連接成功事件 * * @param key */ public static void accept(SelectionKey key) { try { // 獲取客戶端連接通道 ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); // 給通道設(shè)置讀事件,客戶端監(jiān)聽到讀事件后,進(jìn)行讀取操作 sc.register(selector, SelectionKey.OP_READ); System.out.println("accept a client : " + sc.socket().getInetAddress().getHostName()); } catch (IOException e) { e.printStackTrace(); } } /** * 監(jiān)聽到讀事件,讀取客戶端發(fā)送過來的消息 */ public static class NioServerHandler implements Runnable { private SelectionKey selectionKey; public NioServerHandler(SelectionKey selectionKey) { this.selectionKey = selectionKey; } @Override public void run() { try { if (selectionKey.isReadable()) { SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); // 從通道讀取數(shù)據(jù)到緩沖區(qū) ByteBuffer buffer = ByteBuffer.allocate(1024); // 輸出客戶端發(fā)送過來的消息 socketChannel.read(buffer); buffer.flip(); System.out.println("收到客戶端" + socketChannel.socket().getInetAddress().getHostName() + "的數(shù)據(jù):" + new String(buffer.array())); //將數(shù)據(jù)添加到key中 ByteBuffer outBuffer = ByteBuffer.wrap(buffer.array()); // 將消息回送給客戶端 socketChannel.write(outBuffer); selectionKey.cancel(); } } catch (IOException e) { e.printStackTrace(); } } } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75111.html
摘要:前言本篇主要講解中的機(jī)制和網(wǎng)絡(luò)通訊中處理高并發(fā)的分為兩塊第一塊講解多線程下的機(jī)制第二塊講解如何在機(jī)制下優(yōu)化資源的浪費(fèi)服務(wù)器單線程下的機(jī)制就不用我介紹了,不懂得可以去查閱下資料那么多線程下,如果進(jìn)行套接字的使用呢我們使用最簡(jiǎn)單的服務(wù)器來幫助大 前言 本篇主要講解Java中的IO機(jī)制和網(wǎng)絡(luò)通訊中處理高并發(fā)的NIO 分為兩塊:第一塊講解多線程下的IO機(jī)制第二塊講解如何在IO機(jī)制下優(yōu)化CPU資...
摘要:什么是零拷貝我們首先來認(rèn)識(shí)一下傳統(tǒng)的操作。因?yàn)樵谶@套體系里,不僅僅提供了非阻塞的編程模型,而且提供了類似零拷貝,內(nèi)存映射這樣的新技術(shù)對(duì)于操作系統(tǒng)來說早就有了。 什么是零拷貝?我們首先來認(rèn)識(shí)一下傳統(tǒng)的I/O操作。假如說用戶進(jìn)程現(xiàn)在要把一個(gè)文件復(fù)制到另一個(gè)地方。那么用戶程序必須先把這個(gè)文件讀入內(nèi)存,然后再把內(nèi)存里的數(shù)據(jù)寫入另一個(gè)文件。不過文件讀入內(nèi)存也不是直接讀入用戶進(jìn)程的內(nèi)存,而是先讀入...
摘要:的異步即是異步的,也是非阻塞的。但是,也可以進(jìn)行一層稍微薄點(diǎn)的封裝,保留這種多路復(fù)用的模型,比如的,是一種同步非阻塞的模型。系統(tǒng)調(diào)用操作系統(tǒng)的系統(tǒng)調(diào)用提供了多路復(fù)用的非阻塞的系統(tǒng)調(diào)用,這也是機(jī)制實(shí)現(xiàn)需要用到的。 異步IO編程在javascript中得到了廣泛的應(yīng)用,之前也寫過一篇博文進(jìn)行梳理。js的異步IO即是異步的,也是非阻塞的。非阻塞的IO需要底層操作系統(tǒng)的支持,比如在linux上...
摘要:而用于主線程池的屬性都定義在中本篇只是簡(jiǎn)單介紹了一下引導(dǎo)類的配置屬性,下一篇我將詳細(xì)介紹服務(wù)端引導(dǎo)類的過程分析。 從Java1.4開始, Java引入了non-blocking IO,簡(jiǎn)稱NIO。NIO與傳統(tǒng)socket最大的不同就是引入了Channel和多路復(fù)用selector的概念。傳統(tǒng)的socket是基于stream的,它是單向的,有InputStream表示read和Outpu...
摘要:通道可以異步讀寫。使用的方法讀取數(shù)據(jù)創(chuàng)建一個(gè)讀數(shù)據(jù)緩沖區(qū)對(duì)象從通道中讀取數(shù)據(jù)使用的方法寫入數(shù)據(jù)創(chuàng)建一個(gè)寫數(shù)據(jù)緩沖區(qū)對(duì)象寫入數(shù)據(jù)關(guān)閉完成使用后,您必須關(guān)閉它。五提供了一種被稱為的新功能,也稱為本地矢量。功能是通道提供的并不是。 歷史回顧: Java NIO 概覽 Java NIO 之 Buffer(緩沖區(qū)) 其他高贊文章: 面試中關(guān)于Redis的問題看這篇就夠了 一文輕松搞懂redis集...
閱讀 2942·2021-10-28 09:32
閱讀 2967·2021-10-11 10:57
閱讀 3114·2021-10-08 10:05
閱讀 2588·2021-09-28 09:36
閱讀 2213·2019-08-30 15:55
閱讀 2270·2019-08-30 15:44
閱讀 2394·2019-08-30 14:02
閱讀 3076·2019-08-29 17:16