Java中的並發工具類

來源:互聯網
上載者:User

標籤:串連數   length   str   hang   時間長度   主線程   nis   []   訊號   

CountDownLatch  

  CountDownLatch允許一個或多個線程等待其他線程完成操作

  當需要解析一個Excel裡面有多個sheet資料時,可以使用多線程,每個線程解析一個sheet裡的資料。主線程等待所有線程執行完sheet的解析操作。

  

public class JoinCountDownLatchTest(){  public static void main(String[] args){    Thread parser1 = new Thread(new Runnable)_{      public void run(){      }    });    Thread parser2 = new Thread(new Runnable)_{      public void run(){      }    });    parser1.start();    parser2.start();    parser1.join();    parser1.join();    System.out.print("all parsers finished");  }}

  join用於讓當前執行線程等待join線程執行結束。其原理是不停檢查join線程是否存活,若join線程存活則讓當前線程永遠等待。直到join()線程中之後,線程的this.notifyAll()方法會被調用,調用notifyAll()方法是JVM裡實現的。

public class CountDownLatchTest{  static CountDownLatch c = new CountDownLatch(2);  public static void main(String[] args) throws InterruptedException{    new Thread(new Runnable(){      System.out.println(1);      c.countDown();      System.out.println(2);      c.countDown();    }).start();    c.wait();    System.out.println("3");  }}

  CountDownLatch的建構函式接受一個int類型的參數作為計數器,若想等待N個點完成,就傳入N。當我們調用CountDownLatch的countDown方法時,N就減1,CountDownLatch的await方法會阻塞當前線程,直到N變成0。由於countDown方法可以用在任何定法,即可以使N個線程。只需要把這個CountDownLatch的引用傳遞到線程裡即可。若某個線程處理的比較慢,可以使用await的重載方法await(long time, TimeUnit unit)。

  計數器必須大於0,當計數器等於0時,調用await()方法不會阻塞當前線程。CountDownLatch不可能重新初始化或修改CountDownLatch對象的內部計數器的值。一個線程調用countDown方法happen-before另外一個線程調用await方法。

 

同步屏障CyclicBarrier

  CyclicBarrier的意思是可迴圈使用(Cyclic)的屏障(Barrier)。讓一組線程到達一個屏障時被阻塞,直到最後一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續執行。

  CyclicBarrier預設的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每個線程調用await()方法高速CyclicBarrier我已經到達了屏障,然後當前賢臣被阻塞。

public class CyclicBarrireTest{  static CyclicBarrier c = new CyclicBarrier(2);  public static void main(String[] args){    new Thread(new Runnable(){      public void run(){        try{          c.await();        }catch(Exception e){        }        System.out.println(1);      }    }).start();    try{      c.await();    }catch(Exception e){      System.out.println(2);    }  }}

  若把new CyclicBarrier(2)修改成new CyclicBarrire(3),則主線程和子線程會永遠等待,因為沒有第三個線程執行await方法,即沒有第三個線程達到屏障,所以之前到達屏障的兩個線程都不會繼續執行。

  CyclicBarrier還提供給了建構函式CyclicBarrier(int parties, Runnable barrierAction)用於線上程到達屏障時先執行barrierAction。

public class CyclicBarrierTest2{  static CyclicBarrier c = new CyclicBarrier(2, new A());  public static void main(String[] args){    new Thread(new Runnable(){      public void run(){        try{          c.await();         }catch(Exception e){}        System.out.println(1);      }    }).start();    try{       c.await();    }catch(Exception e){}    System.out.println(2);  }  static class A implements Runnable{    public void run(){      System.out.println(3);    }  }}

 

  CyclicBarrier可用於多線程計算資料最後合并計算結果的情境。

public class BankWaterService implements Runnable{  private CyclicBarrier c = new CyclicBarrier(4, this);  private Executor executor = Executors.newFixedThreadPool(4, this);  private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>();    private void count(){    for(int i = 0; i < 4; i++){      executor.execute(new Runnable(){        public void run(){          sheetBankWaterCount.put(Thread.currentThread().getName(), 1);          try{           c.await();           }catch(InterruptedException | BrokenBarrierException e){            e.printStackTrace();          }        }      });    }  }  public void run(){    int result = 0;    for(Entry<String, Integer> sheet : sheetBankWaterCount.entrySet()){      result += sheet.getValue();    }    sheetBankWaterCount.put("result". result);    System.out.println(result);  }  public static void main(String[] args){    BankWaterService bankWaterCount = new BankWaterService();    bankWaterCount.count();  }  }
public class BankWaterService implements Runnable{  private CyclicBarrier c = new CyclicBarrier(4, this);  private Executor executor = Executors.newFixedThreadPool(4, this);  private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>();    private void count(){    for(int i = 0; i < 4; i++){      executor.execute(new Runnable(){        public void run(){          sheetBankWaterCount.put(Thread.currentThread().getName(), 1);          try{           c.await();           }catch(InterruptedException | BrokenBarrierException e){            e.printStackTrace();          }        }      });    }  }  public void run(){    int result = 0;    for(Entry<String, Integer> sheet : sheetBankWaterCount.entrySet()){      result += sheet.getValue();    }    sheetBankWaterCount.put("result". result);    System.out.println(result);  }  public static void main(String[] args){    BankWaterService bankWaterCount = new BankWaterService();    bankWaterCount.count();  }  }

 

CyclicBarrier和CountDownLatch的區別

  CountDownLatch的計數器只能使用一次,而CyclicBarrier的計數器可以使用reset()方法重設。CyclicBarrier還提供了getNumberWaiting方法擷取CyclicBarrier阻塞的線程數量。isBroker()方法用來瞭解阻塞的線程是否被中斷。

 

Semaphore

  Semaphore是用來控制同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公用資源。

  Semaphore可以用於做流量控制,特別是公用資源有限的應用情境,如串連資料庫。

public class SemaphoreTest(){  private static final int THREAD_COUNT = 30;  private static final ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);  private static Semaphore s = new Semaphore(10);  public static void main(String[] args){    for(int i = 0; i < THREAD_COUNT; i++){      threadPool.executor(new Runnable(){        try{         s.acquire();         System.out.println("save data");         s.release();        }catch(InterruptedException e){}      });    }    threadPool.shutdown();  }}

  Semaphore提供如下方法:

    acquire():擷取一個許可證

    release():歸還許可證

    int avaliablePermits():返回訊號量中當前可用的許可認證

    int getQueueLength():返回正在等待擷取許可證的線程書

              boolean hasQueuedThreads():是否有線程正在等待擷取許可證

    void reducePermits(int reduction):減少reduction個許可證,protected

    Collection getQueuedThreads():返回所有等待擷取許可證的線程集合,protected

 

Exchanger

  Exchanger是一個用於線程間協作的工具類。Exchanger用於進行線程間的資料交換。它提供一個同步點,在這個同步點,兩個線程可以交換彼此的資料。這兩個線程通過exchange方法交換資料,若第一個線程先執行exchange()方法,它會一直等待第二個線程也執行exchange()方法,當兩個線程都到達同步點時,這兩個線程可以交換資料,將本線程生產出的資料傳遞給對方。

  Exchange可以用於遺傳演算法,遺傳演算法裡需要選出兩個人作為交配對象,這時候交換兩個人資料,並使用交叉規則得出2個交配的結果。同時Exchanger也可以用於校對工作。為了避免錯誤,採用AB崗兩人進行錄入資料到Excel後,系統載入兩個Excel並對兩個Excel資料進行校對。

public class ExchangerTest{  private static final Exchanger<String> exgr = new Exchanger<String>();  private static ExecutorService threadPool = Executors.newFixedThreadPool(2);    public static void main(String[] args){    threadPool.execute(new Runnble(){      public void run(){        try{          String A = "banker A";          exgr.exchange(A);        }catch(InterruptedException){}      }    });    threadPool.execute(new Runnable(){      public void run(){        String B = "banker B";        String A = exgr.exchange(B);        System.out.println("A equals to B : " + A.equals(B));      }    });  threadPool.shutdown();   }}

  若兩個線程有一個沒有執行exchange()方法,則會一直等待。此時為避免一直等候,可以調用exchange(V x, long timeout, TimeUnit unit)來設定最大等待時間長度。

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.