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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

基础篇--Java IO--概览

發布時間:2023/12/4 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基础篇--Java IO--概览 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

字符流、字節流、輸入流、輸出流

Java 中使用IO(輸入輸出)來讀取和寫入,讀寫磁盤文件、內存、網絡數據。輸入輸出是相對內存而言,往內存中讀數據就為輸入流,從內存中往外寫就是輸出流。
根據處理類型分為字符流、字節流。

  • 字節流處理所有類型數據,以Stream結尾;

  • 字符流處理文本數據,以Reader、Writer結尾;
    Java IO類見下圖:

    同步、異步、阻塞、非阻塞
    synchronous、asynchronous、blocking、non-blocking

    同步、異步關注的是消息通信機制
    同步,是在發起調用后,在得到結果前,該調用不會返回。等到調用返回后,就能拿到返回值。調用者主動等待調用結果。
    異步, 是在發起調用后,調用直接返回,所以無返回結果。后續通過狀態、回調通知調用者。

    阻塞、非阻塞關注的是程序在等待調用結果(返回值、消息)時的狀態
    阻塞調用,是指在調用結果返回前,當前線程會被掛起。調用線程只有在得到結果之后才會返回。
    非阻塞調用,是指在調用結果返回前,該調用不會阻塞當前線程。

    換句話說:
    同步、異步區別:是否需要等待調用結果,才能進行下一步。
    阻塞、非阻塞:進程\線程要訪問的數據就緒前,進程\線程是否需要等待。

Linux的5種IO模型

  • 阻塞IO模型
  • 非阻塞IO模型
  • IO復用模型
  • 信號驅動IO模型
  • 異步IO模型
  • 1.阻塞IO模型
    Linux中,默認情況下socket是阻塞的,一個典型的讀操作流程如下:

    當用戶進程調用了recvfrom這個系統調用,kernel就開始了I/O的第一個階段:準備數據。對于network io來說,很多時候數據在一開始還沒有到達(比如,還沒有收到一個完整的UDP包),這個時候kernel就要等待足夠的數據到來。而在用戶進程這邊,整個進程會被阻塞。
    當kernel一直等到數據準備好了,它就會將數據從kernel系統緩沖區中拷貝到用戶內存,然后kernel返回結果,用戶進程才解除block的狀態,重新運行起來。所以,blocking IO的特點就是在I/O執行的兩個階段都是block。
    Windows Socket API
    socket()函數和WSASocket()函數創建套接字時,默認的套接字是阻塞的。線程會阻塞等待,直到Windows Sockets API執行完成。
    bind()、listen()函數,不會阻塞線程
    可能會阻塞套接字的Windows Socket API調用分為4類

  • 輸入操作:recv()、recvfrom()、WSARecv()和WSARecvfrom()函數。以阻塞套接字為參數的該函數接受數據。如果此時套接字緩沖區中無數據,則調用線程一直睡眠到數據到來

  • 輸出操作:send()、sendto()、WSASend()和WSASendto()函數。調用該函數發送數據。如果套接字緩沖區無可用空間,則調用線程會一直睡眠到有可用空間。

  • 接受連接:accept()和WSAAcept()函數。以阻塞套接字為參數的該函數等待接受對方的連接請求。無則線程休眠。

  • 外出連接:connect()和WSAConnect()函數。對于TCP連接,客戶端以阻塞套接字為參數,調用該函數向服務器發起連接。
    該函數在接收到服務器的應答前,不會返回。 這意味著TCP連接總會等待至少到服務器的一次往返時間。

    阻塞模式的套接字,開發實現簡單。但是并發能力較弱,擴展性弱。

  • 2.非阻塞IO模型
    Linux下,可以設置socket為non-blocking。這種情況下的讀取流程如下:

    用戶進程調用recvfrom()時,如果kernal數據還未準備好,則直接返回error。用戶線程不斷重試,直到kernal準備好后,就馬上將數據拷貝到用戶內存,然后返回。所以這種模式下,用戶線程需要不斷主動詢問kernal數據好了沒。

    3.IO復用模型(IO multiplexing)
    IO復用模型又稱event driven I/O,是在實際中使用最多的I/O模型。基本原理是select/epoll這個方法不斷輪訓所負責的socket,當某個socket有數據到達時,就通知用戶線程。流程如下:

    當用戶線程調用select(),整個線程就會block,同時kernal會監聽所有select負責的socket,一旦有socket的數據準備好了,select()就會返回。這時候用戶線程再去調用read()操作,將數據從kernal拷貝到用戶線程。
    當線程數量較少時,這種方式可能比阻塞I/O模型效率更低,因為多了select()操作。select/epoll的優勢是能處理更多的連接,在高并發場景效率更高。

    4.信號驅動I/O模型(Signal-driven I/O)
    首先我們需要允許套接字使用信號驅動IO,并安裝一個信號處理函數,然后進程繼續運行并不阻塞。當數據準備好時,進程會收到一個SIGIO信號,在信號處理函數中調用IO操作函數處理數據。流程如下:(這種模型在實際中并不常用)

    5.異步I/O模型(Asynchronous I/O)
    這種模型不常用,流程如下:

    用戶線程發起read操作后,立刻就可以去做別的事情。從kernal角度,當它收到一個asynchroous read請求之后,會立刻返回,不會阻塞用戶進程。然后kernal等待數據準備完成,將數據拷貝到用戶內存,之后給用戶進程發送一個signal,告訴它read操作完成了。

    總結
    1:blocking和non-blocking的區別
    blocking IO會阻塞住對應的進程直到操作完成,non-blocking IO在kernal還未準備好數據的時候,直接返回。

    1:synchronous I/O 和asynchronous IO的區別
    區別在于synchronous I/O做I/O操作的時候會將進程阻塞。所以,blocking I/Onon-blocking I/OI/O multiplexingSignal-driven I/O都屬于synchronous I/O,只有Asynchronous I/O屬于asynchronous IO

    擴展:select、poll、epoll簡介
    epoll跟select都能提供多路I/O復用的解決方案。在現在的Linux內核里有都能夠支持,其中epoll是Linux所特有,而select則應該是POSIX所規定,一般操作系統均有實現。
    1.select
    select本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。這樣所帶來的缺點是:

  • 單個進程可監視的fd數量被限制,即能監聽端口的大小有限:
    一般來說這個數目和系統內存關系很大,具體數目可以cat /proc/sys/fs/file-max察看。32位機默認是1024個。64位機默認是2048

  • 對socket進行掃描時是線性掃描,即采用輪詢的方法,效率較低:
    當套接字比較多的時候,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費很多CPU時間。如果能給套接字注冊某個回調函數,當他們活躍時,自動完成相關操作,那就避免了輪詢,這正是epoll與kqueue做的。

  • 需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大

    2.poll
    poll本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然后查詢每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項并繼續遍歷,如果遍歷完所有fd后沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒后它又要再次遍歷fd。這個過程經歷了多次無謂的遍歷。
    它沒有最大連接數的限制,原因是它是基于鏈表來存儲的,但是同樣有一個缺點:

    1. 大量的fd的數組被整體復制于用戶態和內核地址空間之間,而不管這樣的復制是不是有意義 2. poll還有一個特點是“水平觸發”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd

    3.epoll
    epoll支持水平觸發和邊緣觸發,最大的特點在于邊緣觸發,它只告訴進程哪些fd剛剛變為就需態,并且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內核就會采用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知。
    epoll的優點:

  • 沒有最大并發連接的限制,能打開的FD的上限遠大于1024(1G的內存上能監聽約10萬個端口)

  • 效率提升,不是輪詢的方式,不會隨著FD數目的增加效率下降。只有活躍可用的FD才會調用callback函數
    即Epoll最大的優點就在于它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高于select和poll

  • 內存拷貝,利用mmap()文件映射內存加速與內核空間的消息傳遞;即epoll使用mmap減少復制開銷

  • select、poll、epoll 區別

    select內核需要將消息傳遞到用戶空間,都需要內核拷貝動作
    poll同上
    epollepoll通過內核和用戶空間共享一塊內存來實現

    4、Linux I/O模型總結

    綜上,在選擇select,poll,epoll時要根據具體的使用場合以及這三種方式的自身特點:

    1、表面上看epoll的性能最好,但是在連接數少并且連接都十分活躍的情況下,select和poll的性能可能比epoll好,畢竟epoll的通知機制需要很多函數回調。
    2、select低效是因為每次它都需要輪詢。但低效也是相對的,視情況而定,也可通過良好的設計改善

    總結

    以上是生活随笔為你收集整理的基础篇--Java IO--概览的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。