Java 多线程使用
工作中遇到的問題,記錄下解決的思路
?
問題:
對磁盤進行碎片化測試(比如說,磁盤空間是16G),從64K開始寫文件,寫滿后刪除一半,然后寫32K 的數據,寫滿后刪除一半。。。直到4K寫滿刪除一般算是結束
第一階段:
使用單獨的一個線程進行操作,先寫數據,然后刪除數據,用循環控制跳出
代碼
public class Task extends Thread{public void run() {int size = 64;while(size >=4){write(size);delete();size /= 2;}}private void write(int size){//省略具體的寫數據方法,判斷是否寫滿 }private void delete(){//省略刪除的方法 } } View Code上述的代碼已經實現了功能,但是如果空間很大,怎么半?一個線程寫的也太慢了,如何提高效率,寫入的速度?
辦法就是使用多線程,多個線程同時寫,肯定能提升不小的效率
第二階段:
使用多個線程進行操作,代碼和第一階段的代碼沒有變化,共同寫同一個磁盤就行
然后出現了新的問題,多線程操作,到最后肯定會出現剩余的磁盤空間就夠一個線程使用(假如是線程A ),其他線程已經寫完了該階段的內容(假如是線程B,C,D),開始執行刪除操作了,此時,這4個線程有的在寫入數據,有的在刪除數據,會導致線程A一直讀到有剩余空間可以寫入(因為其他線程在刪除文件,騰出新的空間),這樣到最后4K的時候,就出現了A 線程還在寫,其他的線程都已經停止好久了。又浪費了好多時間。
如何解決呢?我想到了使用線程的同步,A線程寫完了就等其他線程,等到所有的線程都寫完了,大家一起開始刪除,等到大家都刪除完成了,再一起開始下一個階段的寫入
那該如何等待呢?
我用了Object類的wait()和notifyAll()方法。
第三階段:
使用同步解決其他線程結束,就剩余一個線程寫的問題,進一步的提高效率
代碼
import java.util.HashMap; import java.util.Map;/*** 狀態信息類*/ public class Status {private int finishCount = 0;private int threadCount = 0;// 存儲每個線程的狀態private Map<Integer, Boolean> maps;public Status(int threadCount) {this.maps = new HashMap<Integer, Boolean>();this.threadCount = threadCount;}//更新當前線程是否在等待狀態,status = true表示已經在等待了public synchronized void setStatus(int threadIndex, boolean statu) {maps.put(threadIndex, statu);}public boolean getStatus() {boolean result = true;for (Map.Entry<Integer, Boolean> entry : maps.entrySet()) {result = result && entry.getValue();}return result;}// 更新已經完成的線程個數(全部各個階段執行完調用)public synchronized void updateFinishCount() {this.finishCount += 1;}public int getFinishCount() {return finishCount;} } View Code /*** 觀察線程*/ public class Watcher extends Thread{private int threadCount = 0;private Status status;public Watcher(Status status,int threadCount ) {this.status = status;this.threadCount = threadCount;}public void run() {while(true){//檢查是否所有status對象上的線程是否都在等待if(status.getStatus()){status.notifyAll();}//檢查是否所有線程全部執行完成if(status.getFinishCount() == threadCount){break;}}} } View Code /*** 具體執行任務的線程*/ public class Task extends Thread{private Status status;private int index;public Task(Status status,int index) {this.status = status;this.index =index;}public void run() {int size = 64;while(size >=4){write(size);synchronized (status) {status.setStatus(index, true);//設置為等待狀態try {status.wait();} catch (InterruptedException e) {e.printStackTrace();}}status.setStatus(index, false);//取消等待狀態 delete();synchronized (status) {status.setStatus(index, true);//設置為等待狀態try {status.wait();} catch (InterruptedException e) {e.printStackTrace();}}status.setStatus(index, false);//取消等待狀態size /= 2;}}private void write(int size){//省略具體的寫數據方法,判斷是否寫滿 }private void delete(){//省略刪除的方法 } } View Code?
現在看起來是完美了,但是實際的運行過程中,會發現,真的沒有控制住線程的同步,還是出現了之前的第二階段的問題,有一個線程比其他線程慢,而且出現了一個線程沒有按照依次遞減的順序執行的古怪情況,我想應該是沒有真正的同步造成的。之后又去查找資料,發現Java提供了一個類,就像是為這種情況量身定做的。它就是 CyclicBarrier??,它自己維護了一個計數器,每當調用一次await()方法,就會阻塞當前的線程,并且計數器減一,計數器的值來源于構造方法,計數器為0的時候,就解除阻塞,更好的是,當計數器為0時,再調用await()方法的時候,會將計數器變成初始值減一,重新開始一個循環。
第四階段:
*** 具體執行任務的線程*/ public class Task extends Thread {private CyclicBarrier cyclicBarrier;public Task(CyclicBarrier cyclicBarrier) {this.cyclicBarrier = cyclicBarrier;}public void run() {int size = 64;while (size >= 4) {write(size);try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {//捕獲到該異常的話,表示這個線程不用等待了,需要處理一下,喚醒其他阻塞的線程 e.printStackTrace();}delete();try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}size /= 2;}}private void write(int size) {// 省略具體的寫數據方法,判斷是否寫滿 }private void delete() {// 省略刪除的方法 } } View Code
?
測試的代碼
public class Test {private static final int THREAD_COUNT = 4;public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT);for(int i=0;i<THREAD_COUNT;i++){new Task(barrier).start();}} } View Code?
?
?
轉載于:https://www.cnblogs.com/android-lol/p/6891872.html
總結
以上是生活随笔為你收集整理的Java 多线程使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Html5 音效播放器
- 下一篇: HTML5 表单 中