Java 多線程使用

來源:互聯網
上載者:User

標籤:nbsp   lap   分享   close   情況   個數   ati   對象   his   

工作中遇到的問題,記錄下解決的思路

 

問題:

   對磁碟進行片段化測試(比如說,磁碟空間是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

 

 

 

  

Java 多線程使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.