java 多線程讀取同一文件
首先在此聲明,本人小菜雞一枚,如有錯誤,還請各位大佬點出並輕點出手,謝謝!!
讀取數據
分析:
如果讀取文件的數據很簡單,但是如果多個線程讀取同一個文件的數據我們該如何處理:
- 待讀取的文件我們可以添加個鎖,目的是維護數據的一致性
- 什麼時候喚醒,什麼時候線程進入阻塞狀態。
針對於這個,我的想法是當一個線程讀取一段長度的文件之後進入阻塞狀態,然後另一個線程繼續讀取。 - 如何讓線程從文件的指定位置讀取。
我問了下度娘,度娘告訴我 file.skip(long n) 可以跳到指定長度 - 設置兩個線程,每個線程讀取的數據長度爲40字符,第一個線程從文件頭開始讀取,讀取40個字符之後,自身進入阻塞狀態,喚醒第二個線程;讓第二個線程從第40個字符開始讀取,讀取40個字符之後喚醒第一個線程,自身進入阻塞狀態,之後喚醒第一個線程。此時線程一處理80 ~ 120字符,並非 40 ~ 80字符。
我們可以這樣理解:文件中有一個標記位,當文件中數據讀取時,標誌位向後移動,由於兩個線程所讀取的文件是共享資源,所以導致標誌位並不會回到最初的起點,而是繼續向下移動。
代碼(只是提供思路,並非最優代碼)
線程1
class fileRead1 implements Runnable {
//待操作文件
private File file;
//標誌對象
private Sign flag;
public fileRead1() {}
public fileRead1(File file, Sign flag) {
this.file = file;
this.flag = flag;
}
public void run() {
FileReader fr = null;
try {
fr = new FileReader(file);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
int length = -1;
char[] buf = new char[40];
synchronized (file) {
try {
while ((length = fr.read(buf)) != -1) {
if (flag.isFlag()) {
System.out.println(new String(buf, 0, length));
flag.setFlag(false);
//喚醒被阻塞的線程
file.notify();
} else {
//自身進入等待狀態
file.wait();
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if (fr != null) {
//加try -atch
fr.close();
}
}
}
}
}
線程2兩處與線程1不同
第一處:
如果不添加 skip 語句,就變成了兩個線程讀取文件的一半內容。
第二處:
if 的條件不同,以及執行之後將標誌對象的屬性更改成true;
標誌類
class Sign {
private boolean flag;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Sign(boolean flag) {
this.flag = flag;
}
public Sign() {}
}
main方法中
File file = new File("F:/創建文件/畫-鄧紫棋.txt");
Sign bz = new Sign(true);
new Thread(new fileRead1(file,bz)).start();
new Thread(new fileRead2(file,bz)).start();