天天看點

13Java進階——IO、線程

BufferInputStream 将建立一個内部的緩沖區數組,内部緩沖區數組将根據需要從包含的輸入流中重新填充,一次可以讀取多個位元組

BufferOutputStream 該類實作緩沖輸出流。 通過設定這樣的輸出流,應用程式可以向底層輸出流寫入位元組,而不必為寫入的每個位元組導緻底層系統的調用

構造方法:傳入位元組流,可以指定緩沖區大小

bos.write("hello\r\n".getBytes(StandardCharsets.UTF_8));

BufferedOutputStream 内部帶有緩沖區 寫資料的時候 先寫出到緩沖區,緩沖區寫滿的時候 ,才會将緩沖區的内容寫出到磁盤 調用flush方法 隻重新整理緩沖流 但不釋放資源 close方法 在關閉流 釋放資源之前 會先重新整理緩沖流

為什麼緩沖流的構造方法中需要的是一個位元組流,而不是具體的檔案或者路徑呢?

位元組緩沖流僅僅提供緩沖區,而真正的讀寫資料還的移開基本的位元組流對象進行操作。

由于位元組流操作中文不是特别友善,是以就出現了字元流

字元流 = 位元組流 +字元集

中文位元組存儲方式

用位元組流複制文本檔案時,文本檔案也會有中文,但是沒有問題,原因就是最終底層操作會自動的進行位元組拼接成中文。

如何識别中文?

漢字在存儲的時候 無論使用那種編碼存儲 第一個位元組都是負數。

編碼就指的是将字元轉換成位元組

string.getBytes(),參數可指定String 字元集名

預設的編碼 UTF-8

// 解碼 編碼和解碼必須使用相同的碼表 否則會出現中文亂碼

解碼: 将位元組數組轉換為字元

String(byte[] bytes, String charsetName)構造一個新的String由指定用指定的位元組的數組解碼charset 。

字元流的抽象基類:

Reader 字元輸入流的抽象基類 編碼

Writer 字元輸出流的抽象基類 解碼

字元流中和編碼相關的類:

InputStreamReader是從位元組流到字元流的橋:它讀取位元組,并使用指定的charset将其解碼為字元 。 它使用的字元集可以由名稱指定,也可以被明确指定,或者可以接受平台的預設字元集。

OutputStreamWriter是字元的橋梁流以位元組流:向其寫入的字元編碼成使用指定的位元組charset 。 它使用的字元集可以由名稱指定,也可以被明确指定,或者可以接受平台的預設字元集。

構造方法:位元組流+可選字元集名

使用字元流完成對于中文的寫和讀

2.4 字元流讀寫的方式

寫:write(字元數組/字元串/字元,起始位置)

重新整理和關閉close(),flush()

讀:read(字元/字元數組,起始位置)

字元流自帶緩沖區

FileReader 是InputStreamReader的簡潔形式

FileWriter 是OutputStreamReader的簡潔形式

BufferedReader

從字元輸入流讀取文本,緩沖字元,以提供字元,數組和行的高效讀取。可以指定緩沖區大小,或者可以使用預設大小。

BufferedReader(Reader in) 建立使用預設大小的輸入緩沖區的緩沖字元輸入流。

readline()讀一行

BufferedWriter

将文本寫入字元輸出流,緩沖字元,以提供單個字元,數組和字元串的高效寫入。

可以指定緩沖區大小,或者可以接受預設大小。

BufferedWriter(Writer out) 建立使用預設大小的輸出緩沖區的緩沖字元輸出流。

newLine()寫分隔符

位元組流可以指派檔案資料,有四種方式一般采用位元組緩沖流一次去屑一個位元組數組的形式。

PrintStream:err、out

InputStream:in

PrintStream ps = System.out;

列印流分為:

位元組 列印流 PrintStream

字元列印流 PrintWtriter

列印流的特點:

隻負責資料的輸出 不能讀取資料

有一些特有的方法 println() print()

對象序列化: 就是将對象儲存到磁盤或者在網絡中傳輸對象 為了對象儲存的正确性 和傳輸的安全性,需要對對象進行編碼處理,那麼把這種處理方式稱為對象的序列化

反序列化:将序列化的對象解析為原對象的過程 就稱為反序列化

ObjectOutputStream oos.writeObject(obj);

ObjectInputStream ois.readObject();再強制轉型

對于對象傳輸 對象必須實作java.io.Serializable接口

Porperties是Map集合的一個實作類

Properties prop = new Properties(); prop.put(k,v); prop.entrySet();

Porperties可以儲存到流中或者從流中加載。 屬性清單中的鍵及其對應的值都是字元串

prop.getProperty(k) prop.setProperty(k,v)

prop.load(輸入位元組流/reader) prop().store(輸出位元組流/writer,注解預設為null)

程式: 是為了完成特定任務 用某種語言編寫的一組指令的集合。指的一段靜态。

程序:是程式的一次執行過程,或是正在運作的一個程式,是一個動态的過程:有他自身的産生 存在 以及消亡的過程--生命周期

程式是靜态的 程序是動态的。程序作為資源配置設定機關,系統在運作時會為每個程序配置設定不同的記憶體區域。

線程(thread) 程序進一步細化就是線程,是一個程式内部的一條執行路徑。

若一個程序同一時間并行執行多個線程,就是支援多線程。

線程作為排程和執行的機關,每個線程擁有獨立的運作棧和程式計數器,線程的切換開銷比較小。

一個程序中的多個線程共享相同的記憶體單元和記憶體位址空間,他們從一個堆中配置設定對象,可以通路相同的變量和對象。這就是的線程間的通信變得簡便和高效。但多個線程操作共享的系統資源可能會帶來安全隐患。

單核CPU和多核CPU

在java中 一個程式至少有三個線程組成, 主線程(main) 垃圾回收線程(gc) 異常處理線程。

并行和并發:

并行:多個CPU同時執行多個任務

并發: 一個CPU在同一時刻,同時處理多個任務。

使用多線程的優點:

1 提高了應用程式的響應。

2 提高了計算機CPU的使用率

3 改善程式結構。

何時需要多線程?

程式需要同時執行兩個或多個任務

程式需要實作一些需要等待的任務的時候:如:使用者輸入,檔案讀寫 網絡操作等。

需要一些背景運作的程式時

建立一個新的執行線程有兩種方法。

一個是将一個類聲明為Thread的子類。 這個子類應該重寫Thread的run方法 。 然後可以配置設定并啟動子類的執行個體

另一種方法來建立一個線程是聲明實作類Runnable接口。 那個類然後實作了run方法。 然後可以配置設定類的執行個體,在建立Thread時作為參數傳遞,并啟動

為什麼要重寫run方法?

因為run方法是用來封裝被線程執行的代碼的。

run方和start方法的差別?

run()封裝了線程執行的代碼,直接調用的,相當于普通方法調用。

start方法 啟動線程,然後由jvm調用此線程的run方法

Runnable接口應由任何類實作,其執行個體将由線程執行。 該類必須定義一個無參數的方法,稱為run

Runnable r = new MyRannable(); Thread t1 = new Thread(r);

t1.start();

或 new Thread(new Runnable(){@Override public void run(){sout;} }).start();

Thread(name):有參構造,參數是線程的名字

th.setName(name);

Thread.currentThread();傳回目前正在執行的線程對象的引用。

th.getName();

th.getPriority();

th.setPriority(pri);

每個線程都有優先權。 具有較高優先級的線程優先于優先級較低的線程執行

線程的兩種排程模型

分時排程: 所有線程輪流實作CPU的使用權,平均配置設定每個線程占有CPU的時間片

搶占式排程: 優先讓優先級高的線程使用CPU,如果線程的優先級相同,那麼會随機選擇一個。優先級高的線程獲得CPU執行權的機率更高。

java是的是搶占式的排程模型。

線程的預設優先級為5,線程的優先級的範圍為1(小)--10(大)