0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Java AIO又稱為NIO 2.0,難道它也是基于NIO來(lái)實(shí)現(xiàn)的?

OSC開(kāi)源社區(qū) ? 來(lái)源:得物技術(shù) ? 2023-03-23 09:26 ? 次閱讀

1

前言

關(guān)于Java BIO、NIO、AIO的區(qū)別和原理,這樣的文章非常的多的,但主要還是在BIO和NIO這兩者之間討論,而關(guān)于AIO這樣的文章就少之又少了,很多只是介紹了一下概念和代碼示例。 在了解AIO時(shí),有注意到以下幾個(gè)現(xiàn)象:

1、 2011年Java 7發(fā)布,里面增加了AIO稱之為異步IO的編程模型,但已經(jīng)過(guò)去了近12年,平時(shí)使用的開(kāi)發(fā)框架中間件,還是以NIO為主,例如網(wǎng)絡(luò)框架Netty、Mina,Web容器Tomcat、Undertow。

2、 Java AIO又稱為NIO 2.0,難道它也是基于NIO來(lái)實(shí)現(xiàn)的?

3、 Netty舍去了AIO的支持。

4、 AIO看起來(lái)只是解決了有無(wú),發(fā)布了個(gè)寂寞。

這幾個(gè)現(xiàn)象不免會(huì)令很多人心存疑惑,所以決定寫(xiě)這篇文章時(shí),不想簡(jiǎn)單的把AIO的概念再?gòu)?fù)述一遍,而是要透過(guò)現(xiàn)象, 如何分析、思考和理解Java AIO的本質(zhì)。

2

什么是異步

2.1 我們所了解的異步

AIO的A是Asynchronous異步的意思,在了解AIO的原理之前,我們先理清一下“異步”到底是怎樣的一個(gè)概念。 說(shuō)起異步編程,在平時(shí)的開(kāi)發(fā)還是比較常見(jiàn),例如以下的代碼示例:


@Async
public void create() {
    //TODO
}


public void build() {
    executor.execute(() -> build());
}

不管是用@Async注解,還是往線程池里提交任務(wù),他們最終都是同一個(gè)結(jié)果,就是把要執(zhí)行的任務(wù),交給另外一個(gè)線程來(lái)執(zhí)行。

這個(gè)時(shí)候,可以大致的認(rèn)為,所謂的“異步”,就是多線程,執(zhí)行任務(wù)。

2.2 Java BIO和NIO到底是同步還是異步?

Java BIO和NIO到底是同步還是異步,我們先按照異步這個(gè)思路,做異步編程。 2.2.1BIO示例

byte [] data = new byte[1024];
InputStream in = socket.getInputStream();
in.read(data);
// 接收到數(shù)據(jù),異步處理
executor.execute(() -> handle(data));


public void handle(byte [] data) {
    // TODO
}
BIO在read()時(shí),雖然線程阻塞了,但在收到數(shù)據(jù)時(shí),可以異步啟動(dòng)一個(gè)線程去處理。 2.2.2NIO示例
selector.select();
Set keys = selector.selectedKeys();
Iterator iterator = keys.iterator();
while (iterator.hasNext()) {
    SelectionKey key = iterator.next();
    if (key.isReadable()) {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
        executor.execute(() -> {
            try {
                channel.read(byteBuffer);
                handle(byteBuffer);
            } catch (Exception e) {


            }
        });


    }
}


public static void handle(ByteBuffer buffer) {
    // TODO
}
同理,NIO雖然read()是非阻塞的,通過(guò)select()可以阻塞等待數(shù)據(jù),在有數(shù)據(jù)可讀的時(shí)候,異步啟動(dòng)一個(gè)線程,去讀取數(shù)據(jù)和處理數(shù)據(jù)。

2.2.3產(chǎn)生理解的偏差

此時(shí)我們信誓旦旦的說(shuō),Java的BIO和NIO是異步還是同步,取決你的心情,你高興給它個(gè)多線程,它就是異步的。 但果真如此么,在翻閱了大量博客文章之后,基本一致的闡明了,BIO和NIO是同步的。

那問(wèn)題點(diǎn)出在哪呢,是什么造成了我們理解上的偏差呢? 那就是參考系的問(wèn)題,以前學(xué)物理時(shí),公交車(chē)上的乘客是運(yùn)動(dòng)還是靜止,需要有參考系前提,如果以地面為參考,他是運(yùn)動(dòng)的,以公交車(chē)為參考,他是靜止的。

Java IO也是一樣,需要有個(gè)參考系,才能定義它是同步異步,既然我們討論的是IO是哪一種模式,那就是要針對(duì)IO讀寫(xiě)操作這件事來(lái)理解,而其他的啟動(dòng)另外一個(gè)線程去處理數(shù)據(jù),已經(jīng)是脫離IO讀寫(xiě)的范圍了,不應(yīng)該把他們扯進(jìn)來(lái)。

2.2.4嘗試定義異步

所以以IO讀寫(xiě)操作這事件作為參照,我們先嘗試的這樣定義,就是發(fā)起IO讀寫(xiě)的線程(調(diào)用read和write的線程),和實(shí)際操作IO讀寫(xiě)的線程,如果是同一個(gè)線程,就稱之為同步,否則是異步

顯然BIO只能是同步,調(diào)用in.read()當(dāng)前線程阻塞,有數(shù)據(jù)返回的時(shí)候,接收到數(shù)據(jù)的還是原來(lái)的線程。

而NIO也稱之為同步,原因也是如此,調(diào)用channel.read()時(shí),線程雖然不會(huì)阻塞,但讀到數(shù)據(jù)的還是當(dāng)前線程。

按照這個(gè)思路,AIO應(yīng)該是發(fā)起IO讀寫(xiě)的線程,和實(shí)際收到數(shù)據(jù)的線程,可能不是同一個(gè)線程 是不是這樣呢,現(xiàn)在開(kāi)始上Java AIO的代碼。

2.3 Java AIO的程序示例

2.3.1 AIO服務(wù)端程序


public class AioServer {


    public static void main(String[] args) throws IOException {
        System.out.println(Thread.currentThread().getName() + " AioServer start");
        AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open()
                .bind(new InetSocketAddress("127.0.0.1", 8080));
        serverChannel.accept(null, new CompletionHandler() {


            @Override
            public void completed(AsynchronousSocketChannel clientChannel, Void attachment) {
                System.out.println(Thread.currentThread().getName() + " client is connected");
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                clientChannel.read(buffer, buffer, new ClientHandler());
            }


            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("accept fail");
            }
        });
        System.in.read();
    }
}


public class ClientHandler implements CompletionHandler {
    @Override
    public void completed(Integer result, ByteBuffer buffer) {
        buffer.flip();
        byte [] data = new byte[buffer.remaining()];
        buffer.get(data);
        System.out.println(Thread.currentThread().getName() + " received:"  + new String(data, StandardCharsets.UTF_8));
    }


    @Override
    public void failed(Throwable exc, ByteBuffer buffer) {


    }
}

2.3.2 AIO客戶端程序

public class AioClient {


    public static void main(String[] args) throws Exception {
        AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
        channel.connect(new InetSocketAddress("127.0.0.1", 8080));
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put("Java AIO".getBytes(StandardCharsets.UTF_8));
        buffer.flip();
        Thread.sleep(1000L);
        channel.write(buffer);
 }
}

2.3.3 異步的定義猜想結(jié)論

分別運(yùn)行服務(wù)端和客戶端程序

b0c449bc-c8e0-11ed-bfe3-dac502259ad0.png

在服務(wù)端運(yùn)行結(jié)果里, main線程發(fā)起serverChannel.accept的調(diào)用,添加了一個(gè)CompletionHandler監(jiān)聽(tīng)回調(diào),當(dāng)有客戶端連接過(guò)來(lái)時(shí),Thread-5線程執(zhí)行了accep的completed回調(diào)方法。 緊接著Thread-5又發(fā)起了clientChannel.read調(diào)用,也添加了個(gè)CompletionHandler監(jiān)聽(tīng)回調(diào),當(dāng)收到數(shù)據(jù)時(shí),是Thread-1的執(zhí)行了read的completed回調(diào)方法。

這個(gè)結(jié)論和上面異步猜想一致,發(fā)起IO操作(例如accept、read、write)調(diào)用的線程,和最終完成這個(gè)操作的線程不是同一個(gè),我們把這種IO模式稱之AIO, 當(dāng)然了,這樣定義AIO只是為了方便我們理解,實(shí)際中對(duì)異步IO的定義可能更抽象一點(diǎn)。

3

AIO示例引發(fā)思考的問(wèn)題

1、 執(zhí)行completed()方法的這個(gè)線程是誰(shuí)創(chuàng)建的,什么時(shí)候創(chuàng)建的?

2、 AIO注冊(cè)事件監(jiān)聽(tīng)和執(zhí)行回調(diào)是如何實(shí)現(xiàn)的?

3、 監(jiān)聽(tīng)回調(diào)的本質(zhì)是什么?

3.1 問(wèn)題1:執(zhí)行completed()方法的這個(gè)線程是誰(shuí)創(chuàng)建的,什么時(shí)候創(chuàng)建的

一般,這樣的問(wèn)題,需要從程序的入口的開(kāi)始了解,但跟線程相關(guān),其實(shí)是可以從線程棧的運(yùn)行情況來(lái)定位線程是怎么運(yùn)行。 只運(yùn)行AIO服務(wù)端程序,客戶端不運(yùn)行,打印一下線程棧(備注:程序在Linux平臺(tái)上運(yùn)行,其他平臺(tái)略有差異)

b0dc3cfc-c8e0-11ed-bfe3-dac502259ad0.png

分析線程棧,發(fā)現(xiàn),程序啟動(dòng)了那么幾個(gè)線程

1、 線程Thread-0阻塞在EPoll.wait()方法上

2、 線程Thread-1、Thread-2。。。Thread-n(n和CPU核心數(shù)量一致)從阻塞隊(duì)列里take()任務(wù),阻塞等待有任務(wù)返回。 此時(shí)可以暫定下一個(gè)結(jié)論: AIO服務(wù)端程序啟動(dòng)之后,就開(kāi)始創(chuàng)建了這些線程,且線程都處于阻塞等待狀態(tài)。

另外,發(fā)現(xiàn)這些線程的運(yùn)行都跟Epoll有關(guān)系,提到Epoll,我們印象中,Java NIO在Linux平臺(tái)底層就是用Epoll來(lái)實(shí)現(xiàn)的,難道Java AIO也是用Epoll來(lái)實(shí)現(xiàn)么?為了證實(shí)這個(gè)結(jié)論,我們從下一個(gè)問(wèn)題來(lái)展開(kāi)討論

3.2 問(wèn)題2:AIO注冊(cè)事件監(jiān)聽(tīng)和執(zhí)行回調(diào)是如何實(shí)現(xiàn)的

帶著這個(gè)問(wèn)題,去閱讀分析源碼時(shí),發(fā)現(xiàn)源碼特別的長(zhǎng),而源碼解析是一項(xiàng)枯燥乏味的過(guò)程,很容易把閱讀者給逼走勸退掉。

對(duì)于長(zhǎng)流程和邏輯復(fù)雜的代碼的理解,我們可以抓住它幾個(gè)脈絡(luò),找出哪幾個(gè)核心流程。

以注冊(cè)監(jiān)聽(tīng)read為例clientChannel.read(...),它主要的核心流程是: 1、注冊(cè)事件 -> 2、監(jiān)聽(tīng)事件 -> 3、處理事件

3.2.1 1、注冊(cè)事件

b1688eaa-c8e0-11ed-bfe3-dac502259ad0.png

注冊(cè)事件調(diào)用EPoll.ctl(...)函數(shù),這個(gè)函數(shù)在最后的參數(shù)用于指定是一次性的,還是永久性。

上面代碼events | EPOLLONSHOT字面意思看來(lái),是一次性的。

3.2.2 2、監(jiān)聽(tīng)事件

b1a00cae-c8e0-11ed-bfe3-dac502259ad0.png

3.2.3 3、處理事件

b1cb0a94-c8e0-11ed-bfe3-dac502259ad0.pngb1f79adc-c8e0-11ed-bfe3-dac502259ad0.pngb2315420-c8e0-11ed-bfe3-dac502259ad0.png

3.2.4 核心流程總結(jié)

b250eede-c8e0-11ed-bfe3-dac502259ad0.png

在分析完上面的代碼流程后會(huì)發(fā)現(xiàn),每一次IO讀寫(xiě)都要經(jīng)歷的這三個(gè)事件是一次性的,也就是在處理事件完,本次流程就結(jié)束了,如果想繼續(xù)下一次的IO讀寫(xiě),就得從頭開(kāi)始再來(lái)一遍。這樣就會(huì)存在所謂的死亡回調(diào)(回調(diào)方法里再添加下一個(gè)回調(diào)方法),這對(duì)于編程的復(fù)雜度大大提高了。

3.3 問(wèn)題3: 監(jiān)聽(tīng)回調(diào)的本質(zhì)是什么?

先說(shuō)一下結(jié)論,所謂監(jiān)聽(tīng)回調(diào)的本質(zhì),就是用戶態(tài)線程,調(diào)用內(nèi)核態(tài)的函數(shù)(準(zhǔn)確的說(shuō)是API,例如read,write,epollWait),該函數(shù)還沒(méi)有返回時(shí),用戶線程被阻塞了。

當(dāng)函數(shù)返回時(shí),會(huì)喚醒阻塞的線程,執(zhí)行所謂回調(diào)函數(shù)。
對(duì)于這個(gè)結(jié)論的理解,要先引入幾個(gè)概念

3.3.1 系統(tǒng)調(diào)用與函數(shù)調(diào)用

函數(shù)調(diào)用: 找到某個(gè)函數(shù),并執(zhí)行函數(shù)里的相關(guān)命令 系統(tǒng)調(diào)用: 操作系統(tǒng)對(duì)用戶應(yīng)用程序提供了編程接口,所謂API。

系統(tǒng)調(diào)用執(zhí)行過(guò)程:

1.傳遞系統(tǒng)調(diào)用參數(shù)

2.執(zhí)行陷入指令,用用戶態(tài)切換到核心態(tài),這是因?yàn)橄到y(tǒng)調(diào)用一般都需要再核心態(tài)下執(zhí)行

3.執(zhí)行系統(tǒng)調(diào)用程序

4.返回用戶態(tài)

3.3.2 用戶態(tài)和內(nèi)核態(tài)之間的通信

用戶態(tài)->內(nèi)核態(tài),通過(guò)系統(tǒng)調(diào)用方式即可。 內(nèi)核態(tài)->用戶態(tài),內(nèi)核態(tài)根本不知道用戶態(tài)程序有什么函數(shù),參數(shù)是啥,地址在哪里。所以內(nèi)核是不可能去調(diào)用用戶態(tài)的函數(shù),只能通過(guò)發(fā)送信號(hào),比如kill 命令關(guān)閉程序就是通過(guò)發(fā)信號(hào)讓用戶程序優(yōu)雅退出的。

既然內(nèi)核態(tài)是不可能主動(dòng)去調(diào)用用戶態(tài)的函數(shù),為什么還會(huì)有回調(diào)呢,只能說(shuō)這個(gè)所謂回調(diào)其實(shí)就是用戶態(tài)的自導(dǎo)自演。它既做了監(jiān)聽(tīng),又做了執(zhí)行回調(diào)函數(shù)。

3.3.3 用實(shí)際例子驗(yàn)證結(jié)論

為了驗(yàn)證這個(gè)結(jié)論是否有說(shuō)服力,舉個(gè)例子,平時(shí)開(kāi)發(fā)寫(xiě)代碼用的IntelliJ IDEA,它是如何監(jiān)聽(tīng)鼠標(biāo)、鍵盤(pán)事件和處理事件的。 按照慣例,先打印一下線程棧,會(huì)發(fā)現(xiàn)鼠標(biāo)、鍵盤(pán)等事件的監(jiān)聽(tīng)是由"AWT-XAWT"線程負(fù)責(zé)的,處理事件則是"AWT-EventQueue"線程負(fù)責(zé)。

b28d98de-c8e0-11ed-bfe3-dac502259ad0.png

定位到具體的代碼上,可以看到"AWT-XAWT"正在做while循環(huán),調(diào)用waitForEvents函數(shù)等待事件返回。如果沒(méi)有事件,線程就一直阻塞在那邊。

b2f3c492-c8e0-11ed-bfe3-dac502259ad0.png

4

Java AIO的本質(zhì)是什么?

1、由于內(nèi)核態(tài)無(wú)法直接調(diào)用用戶態(tài)函數(shù),Java AIO的本質(zhì),就是只在用戶態(tài)實(shí)現(xiàn)異步。并沒(méi)有達(dá)到理想意義上的異步。

理想中的異步 何謂理想意義上的異步?這里舉個(gè)網(wǎng)購(gòu)的例子 兩個(gè)角色,消費(fèi)者A,快遞員B

A在網(wǎng)上購(gòu)物時(shí),填好家庭地址付款提交訂單,這個(gè)相當(dāng)于注冊(cè)監(jiān)聽(tīng)事件

商家發(fā)貨,B把東西送到A家門(mén)口,這個(gè)相當(dāng)于回調(diào)。

A在網(wǎng)上下完單,后續(xù)的發(fā)貨流程就不用他來(lái)操心了,可以繼續(xù)做其他事。B送貨也不關(guān)心A在不在家,反正就把貨扔到家門(mén)口就行了,兩個(gè)人互不依賴,互不相干擾。 假設(shè)A購(gòu)物是用戶態(tài)來(lái)做,B送快遞是內(nèi)核態(tài)來(lái)做,這種程序運(yùn)行方式過(guò)于理想了,實(shí)際中實(shí)現(xiàn)不了。

現(xiàn)實(shí)中的異步 A住的是高檔小區(qū),不能隨意進(jìn)去,快遞只能送到小區(qū)門(mén)口。 A買(mǎi)了一件比較重的商品,比如一臺(tái)電視,因?yàn)锳要上班不在家里,所以找了一個(gè)好友C幫忙把電視搬到他家。 A出門(mén)上班前,跟門(mén)口的保安D打聲招呼,說(shuō)今天有一臺(tái)電視送過(guò)來(lái),送到小區(qū)門(mén)口時(shí),請(qǐng)電話聯(lián)系C,讓他過(guò)來(lái)拿。

此時(shí),A下單并跟D打招呼,相當(dāng)于注冊(cè)事件。在AIO中就是EPoll.ctl(...)注冊(cè)事件。

保安在門(mén)口蹲著相當(dāng)于監(jiān)聽(tīng)事件,在AIO中就是Thread-0線程,做EPoll.wait(..)

快遞員把電視送到門(mén)口,相當(dāng)于有IO事件到達(dá)。

保安通知C電視到了,C過(guò)來(lái)搬電視,相當(dāng)于處理事件。在AIO中就是Thread-0往任務(wù)隊(duì)列提交任務(wù),Thread-1 ~n去取數(shù)據(jù),并執(zhí)行回調(diào)方法。

整個(gè)過(guò)程中,保安D必須一直蹲著,寸步不能離開(kāi),否則電視送到門(mén)口,就被人偷了。 好友C也必須在A家待著,受人委托,東西到了,人卻不在現(xiàn)場(chǎng),這有點(diǎn)失信于人。

所以實(shí)際的異步和理想中的異步,在互不依賴,互不干擾,這兩點(diǎn)相違背了。保安的作用最大,這是他人生的高光時(shí)刻。 異步過(guò)程中的注冊(cè)事件、監(jiān)聽(tīng)事件、處理事件,還有開(kāi)啟多線程,這些過(guò)程的發(fā)起者全是用戶態(tài)一手操辦,所以說(shuō)Java AIO只在用戶態(tài)實(shí)現(xiàn)了異步,這個(gè)和BIO、NIO先阻塞,阻塞喚醒后開(kāi)啟異步線程處理的本質(zhì)一致。

2、Java AIO跟NIO一樣,在各個(gè)平臺(tái)的底層實(shí)現(xiàn)方式也不同,在Linux是用EPoll,Windows是IOCP,Mac OS是KQueue。原理是大同小異,都是需要一個(gè)用戶線程阻塞等待IO事件,一個(gè)線程池從隊(duì)列里處理事件。

3、 Netty之所以移除掉AIO,很大的原因是在性能上AIO并沒(méi)有比NIO高。Linux雖然也有一套原生的AIO實(shí)現(xiàn)(類(lèi)似Windows上的IOCP),但Java AIO在Linux并沒(méi)有采用,而是用EPoll來(lái)實(shí)現(xiàn)。

4、 Java AIO不支持UDP

5、 AIO編程方式略顯復(fù)雜,比如“死亡回調(diào)”






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11158

    瀏覽量

    208459
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2946

    瀏覽量

    104361
  • AIO
    AIO
    +關(guān)注

    關(guān)注

    1

    文章

    61

    瀏覽量

    9950
  • Thread
    +關(guān)注

    關(guān)注

    2

    文章

    83

    瀏覽量

    25868

原文標(biāo)題:透過(guò)現(xiàn)象看Java AIO的本質(zhì)

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    BIO、NIOAIO 模型工作方式

    一、簡(jiǎn)介 在計(jì)算機(jī)中,IO 傳輸數(shù)據(jù)有三種工作方式,分別是: BIO、NIO、AIO 。 在講解 BIO、NIO、AIO 之前,我們先來(lái)回顧一下這幾個(gè)概念: 同步與異步,阻塞與非阻塞
    的頭像 發(fā)表于 09-30 10:43 ?436次閱讀
    BIO、<b class='flag-5'>NIO</b>、<b class='flag-5'>AIO</b> 模型工作方式

    IO與NIO有何區(qū)別

    NIO 提到IO,這是Java提供的一套類(lèi)庫(kù),用于支持應(yīng)用程序與內(nèi)存、文件、網(wǎng)絡(luò)間進(jìn)行數(shù)據(jù)交互,實(shí)現(xiàn)數(shù)據(jù)寫(xiě)入與輸出。JDK自從1.4版本后,提供了另一套類(lèi)庫(kù)NIO,我們平時(shí)習(xí)慣稱呼為N
    的頭像 發(fā)表于 09-25 11:00 ?772次閱讀
    IO與<b class='flag-5'>NIO</b>有何區(qū)別

    Java NIO編程理論基礎(chǔ)之Java IO及l(fā)inux網(wǎng)絡(luò)IO模型發(fā)展

    Java NIO編程理論基礎(chǔ)篇——Java IO的發(fā)展以及l(fā)inux網(wǎng)絡(luò)IO模型
    發(fā)表于 07-18 12:40

    Java NIO反應(yīng)器模式設(shè)計(jì)

    Javal.4引入的NIO包里,最引人注目的是加入了非阻塞I/O。和IO包提供的阻塞模型不同,NIO在對(duì)一個(gè)非阻塞的連接進(jìn)行操作時(shí),調(diào)用會(huì)立即返回,而不是掛起等待.
    發(fā)表于 01-05 16:06 ?38次下載
    <b class='flag-5'>Java</b> <b class='flag-5'>NIO</b>反應(yīng)器模式設(shè)計(jì)

    Java NIO (中文版)編程總結(jié)

    Java NIO 編程總結(jié)
    發(fā)表于 09-21 11:17 ?0次下載

    JavaNIO的基本概念

    一.NIO中的幾個(gè)基礎(chǔ)概念 在NIO中有幾個(gè)比較關(guān)鍵的概念:Channel(通道),Buffer(緩沖區(qū)),Selector(選擇器)。 首先從Channel說(shuō)起吧,通道,顧名思義,就是通向什么的
    發(fā)表于 09-27 10:44 ?0次下載
    <b class='flag-5'>Java</b>之<b class='flag-5'>NIO</b>的基本概念

    來(lái)(NIO)為何緣故,要大規(guī)模裁員?

    在網(wǎng)名“紙孩子”率先爆料蔚來(lái)(NIO)大規(guī)模裁員和回租等系列內(nèi)幕后,蔚來(lái)汽車(chē)以一份無(wú)章、無(wú)抬頭的回應(yīng)“辟謠”。
    發(fā)表于 03-27 15:54 ?1473次閱讀

    來(lái)推送L2級(jí)別自動(dòng)輔助駕駛功能和NIO OS 2.0智能操作系統(tǒng)

    6月10日,NIO Pilot自動(dòng)輔助駕駛系統(tǒng)迎來(lái)升級(jí),本次新增7項(xiàng)功能;同時(shí)推送升級(jí)的還有NIO OS 2.0智能操作系統(tǒng),全新的UX交互和全新的UI設(shè)計(jì)將帶來(lái)全新的數(shù)字化體驗(yàn)。
    發(fā)表于 06-17 09:12 ?1201次閱讀

    來(lái)NIO OS 2.5.0版本升級(jí) NOMI體驗(yàn)更加合理和完善

    2月20日,蔚來(lái)發(fā)布了NIO OS 2.5.0版本的升級(jí),也是進(jìn)入NIO OS 2.0階段第5次大升級(jí),將會(huì)陸續(xù)通過(guò)FOTA對(duì)當(dāng)前版本為2.
    發(fā)表于 03-08 08:59 ?3059次閱讀

    JAVANIO通過(guò)MappedByteBuffer操作大文件

    java io操作中通常采用BufferedReader,BufferedInputStream等帶緩沖的IO類(lèi)處理大文件,不過(guò)java nio中引入了一種基于MappedByteBuffer操作大文件的方式,其讀寫(xiě)性能極高,本
    的頭像 發(fā)表于 05-05 23:42 ?3443次閱讀

    來(lái)NIO Day發(fā)布的新產(chǎn)品都有哪些亮點(diǎn)?

    而此前經(jīng)多輪預(yù)熱、成為焦點(diǎn)的蔚來(lái)新品發(fā)布環(huán)節(jié),卻只占將近三個(gè)小時(shí)NIO Day的1/4時(shí)間,以至于被外界戲稱為“真的只是一個(gè)‘節(jié)目’”。
    的頭像 發(fā)表于 01-12 10:38 ?2691次閱讀

    來(lái)NIO Phone發(fā)布:蔚來(lái)風(fēng)格,旗艦選擇

    NIO Phone 亮點(diǎn)一覽 第二代驍龍8領(lǐng)先版 標(biāo)志性天際線設(shè)計(jì)與純粹系統(tǒng) 高通3D Sonic Max超聲波指紋傳感器 5000萬(wàn)像素三主攝 以車(chē)為中心的移動(dòng)互聯(lián)全新體驗(yàn) 今日,在2023蔚來(lái)
    的頭像 發(fā)表于 09-22 00:00 ?644次閱讀
    蔚<b class='flag-5'>來(lái)</b><b class='flag-5'>NIO</b> Phone發(fā)布:蔚<b class='flag-5'>來(lái)</b>風(fēng)格,旗艦選擇

    來(lái)手機(jī)9月28日開(kāi)始發(fā)貨 NIO Phone起售價(jià)6499

    來(lái)手機(jī)9月28日開(kāi)始發(fā)貨 NIO Phone起售價(jià)6499 蔚來(lái)造手機(jī)、小米造車(chē),不知道以后華為會(huì)要造什么?或者蘋(píng)果造車(chē)? 蔚來(lái)用戶需要一款與蔚來(lái)汽車(chē)無(wú)縫連接的手機(jī)。所以蔚
    的頭像 發(fā)表于 09-26 18:39 ?759次閱讀

    來(lái)NIO Phone體驗(yàn)報(bào)告:智能體驗(yàn)超出預(yù)期,車(chē)手互聯(lián)頗有驚喜

    來(lái)了專(zhuān)為車(chē)主打造的NIO Link蔚來(lái)全景互聯(lián)技術(shù),實(shí)現(xiàn)了車(chē)機(jī)與手機(jī)的生態(tài)系統(tǒng)閉環(huán)。本期體驗(yàn)報(bào)告,不妨一起來(lái)看看NIO Phone帶來(lái)的多項(xiàng)創(chuàng)新驚喜吧。 蔚
    的頭像 發(fā)表于 12-15 20:45 ?1155次閱讀
    蔚<b class='flag-5'>來(lái)</b><b class='flag-5'>NIO</b> Phone體驗(yàn)報(bào)告:智能體驗(yàn)超出預(yù)期,車(chē)手互聯(lián)頗有驚喜

    來(lái)宣布完成NIO Phone 2研發(fā),每年僅發(fā)布一款新機(jī)

    值得注意的是,早在2023年9月的蔚來(lái)創(chuàng)新科技日,李斌曾在接受媒體采訪時(shí)透露,蔚來(lái)手機(jī)會(huì)持續(xù)迭代,研發(fā)周期已形成“固定模式”,第二代NIO Phone正處于研發(fā)當(dāng)中。而在同年12月,蔚來(lái)自家推出首款智能手機(jī)——蔚
    的頭像 發(fā)表于 03-19 15:40 ?1229次閱讀