[AcWing 3] 完全揹包問題
什麼是IO?
IO:指的是輸入(input)和輸出(output)。
什麼是流?
流:指的是一連串的資料(位元組或字元),以先進先出的方式傳送資訊的通道。
當程式需要讀取資料的時候,就會開啟一個通向資料來源的流,這個資料來源可以是檔案,記憶體,或是網路連線。
類似的,當程式需要寫入資料時,就會開啟一個通向目的地的流。
IO流的分類
1.按資料流的方向:輸入流和輸出流(inputStream和outputStream)
輸入和輸出是相對於應用程式而言的,比如檔案讀寫,讀取檔案是輸入流,寫檔案是輸出流,不要搞反了
2.按處理資料單位:位元組流(inputStream和outputStream
位元組流和字元流的用法幾乎完全一樣,區別1.在於位元組流和字元流所操作的資料單元不同,位元組流操作的單元是
8位的位元組,而字元流操作的是資料單元是為16位的字元。2.字元流一般用於處理純文字型別的檔案,如TXT檔案等,
不能用來處理影象視訊等非文字檔案。即位元組流可以處理一切檔案,而字元流只能處理純文字檔案。3.位元組流本身沒有緩衝區
緩衝位元組流相對於位元組流,效率提升非常高。而字元流本身就帶有緩衝區,緩衝字元流相對於字元流效率提升不是很大。
3.按功能:節點流和處理流
節點流:直接操作資料讀寫的流類,比如FileInputStream
處理流:對一個已存在的流的連結和封裝,通過對資料進行處理為程式提供強大、靈活的讀寫功能,比如,BufferInputStream(即緩衝位元組流)
處理流和節點流應用了Java的裝飾者模式。
緩衝流,也是處理流的一種,能夠減少程式與磁碟之間的互動,是提升程式效率的一種有效手段。
思路:緩衝流在記憶體中設定一個緩衝區,緩衝區先儲存足夠的待操作資料後,再與記憶體或磁碟進行互動。
這樣的話,在總資料量不變的情況下,通過提高每次互動的資料量,減少了互動次數。
注意:緩衝流效率一定高嗎?在某些情形下,緩衝流效率反而更低。
FIle類是用來操作檔案的類,但他不能操作檔案中的資料,他實現了Serializable、Comparable<File>,說明他是支援序列化和排序的。
位元組流:InputStream和OutputStream是兩個抽象類,是位元組流的基類,所有的具體位元組流實現類都是繼承了這兩個類。
字元流:Writer和Reader是兩個抽象類,其它的字元流實現類都是繼承了這兩個類。
Java序列化(Serialization)和反序列化(DeSerialization)
序列化:把物件轉化為位元組序列的過程稱為物件的序列化。
為什麼要序列化:我們需要把資料儲存到磁碟即持久化。
反序列化:把位元組序列恢復為物件的過程稱為物件的反序列化
ObjectOutputStream表示物件輸出流,它的writeObject()方法從可以對引數指定的object物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。
ObjectInputStream()方法從源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。
注意:1.序列化時,只對物件的狀態進行 儲存,而不管物件的方法。
2.當一個父類實現序列化,子類自動實現序列化,不需要顯示實現Serialization介面
3.當一個物件的例項變數引用其它物件,序列化該物件時,也把引用物件進行序列化
4.並非所有的物件都可以序列化,比如:宣告為static(代表類的狀態)和transient(代表物件的臨時資料)型別的資料不能被序列化。
BIO(blocking IO):即同步阻塞,伺服器實現模式為一個連線一個執行緒,即客戶端有連線請求使時務器就需要啟動一個執行緒進行處理,
如果這個連線不做任何事情會造成不必要的執行緒開銷。
NIO(non-blocking IO):即同步非阻塞,伺服器
NIO三大核心部分:Channel(通道),Buffer(緩衝區),Selector(選擇器)
NIO是面向緩衝區的,或者面向塊程式設計的。資料讀取到一個它稍後處理的緩衝區,需要時可在緩衝區內前後,這就增加了處理過程中的靈活性,使用它可以提供非阻塞的高伸縮性網路。
Java NIO的非阻塞模式,使一個執行緒從某通道傳送或者讀取資料,但它僅能得到目前可用的資料,如果目前沒有可用的資料時,就什麼都不會獲取,而不是保持執行緒阻塞,
所以直至資料變的可讀取之前,該執行緒可以繼續做其他的事情。非阻塞就是如此,一個執行緒請求寫入一些資料到某通道,但不需要等待它完全寫入,這個執行緒同時可以去做別的事情。
BIO和NIO的區別
1.BIO以流的方式處理資料,NIO以塊的方式處理資料,塊的效率比流的效率高很多。
2.BIO是阻塞的,NIO是非阻塞的。
3.BIO基於位元組流和字元流進行操作的,而NIO基於Channel和Buffer進行操作的,資料總是從通道讀取到緩衝區中,或者從緩衝區寫入到
通道中。Selector用於監聽多個通道事件,因此使用單個執行緒就可以監聽多個客戶端通道。
IO多路複用
先了解最基本的Socket模型
想要客戶端和伺服器能在網路中同信,那必須得使Socket程式設計,它是程序間通訊裡比較特別的方式---->他可以跨主機間通訊。
Socket的中文名叫作插口,客戶端和伺服器在進行網路通訊前,各自得建立一個Socket,這相當於客戶端和伺服器打開了一個
“口子”。就像手機充電一樣,得用一根資料線,一頭插在手機充電口,一頭插在插座上,然後進行充電。
如果每次都為客戶端分配一個程序/執行緒來處理請求,那就意味著一萬個請求是不是要分配一萬個程序/執行緒???
所以有沒有一種可能,我們只使用一個程序來維護多個Socket???當然是有的,————IO多路複用技術。
一個程序雖然任意時刻只能處理一個請求,但是處理每個請求,但是每個請求的事件時,耗時可以控制在1毫秒以內,這樣
1秒內就可以處理上千個請求,把時間拉長來看,多個請求複用了一個執行緒,這就是多路複用,類似於一個CPU併發處理多個執行緒,所以也叫時分多路複用。