java 線程使用整理

java 多線程讀取同一文件

首先在此聲明,本人小菜雞一枚,如有錯誤,還請各位大佬點出並輕點出手,謝謝!!

讀取數據

分析:
如果讀取文件的數據很簡單,但是如果多個線程讀取同一個文件的數據我們該如何處理:

  1. 待讀取的文件我們可以添加個鎖,目的是維護數據的一致性
  2. 什麼時候喚醒,什麼時候線程進入阻塞狀態。
    針對於這個,我的想法是當一個線程讀取一段長度的文件之後進入阻塞狀態,然後另一個線程繼續讀取。
  3. 如何讓線程從文件的指定位置讀取。
    我問了下度娘,度娘告訴我 file.skip(long n) 可以跳到指定長度
  4. 設置兩個線程,每個線程讀取的數據長度爲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();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章