1)閉鎖CountDownLatch數據庫
功能:讓一個主線程等待一組工做線程執行完畢以後,才繼續執行主線程,與join()方法的功能相似。 原理: 1)CountDownLatch是經過一個計數器來實現的,計數器的初始值爲須要等待線程的數量。 2)當一個線程完成了本身的任務後,計數器的值就會減1。 3)當計數器值爲0時,說明全部的線程都執行完了,此時,在閉鎖上等待的線程就能夠恢復執行任務。 注意: 1)countDown()能夠在每一個線程中調用一次,也能夠在一個線程中調用屢次。 2)計數器必須大於等於0,計數器爲0時,調用await方法時不會阻塞當前線程。
2)屏障(柵欄)CyclicBarrier併發
功能:讓一組線程到達一個屏障時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門(trip),全部被屏障攔截的線程纔會繼續運行。 CyclicBarrier和CountDownLatch的區別: 1)CountDownLatch的計數器只能使用一次,而CyclicBarrier的計數器能夠使用reset()方法重置。 2)到達某個點後,使用CountDownLatch的線程繼續運行,使用CyclicBarrier的線程中止運行: 使用CountDownLatch的線程運行到某個點以後,調用 countDown() 方法將計數器的值減1,以後線程繼續執行。 使用CyclicBarrier 的線程運行到某個點以後,調用 await() 方法使該線程中止運行,直到全部的線程都到達了這個點(調用await方法),(全部的)線程才能夠繼續運行。
3)信號量Semaphoreui
功能:控制併發的線程數。 原理: 1)線程經過acquire()方法獲取許可證。 2)線程經過release()方法歸還許可證。 說明:使用tryAcquire()方法能夠當即獲得執行的結果:嘗試獲取一個許可證,若獲取成功,則當即返回true,若獲取失敗,則當即返回false。 應用:流量控制,例如數據庫鏈接數的控制等。
4)交換者Exchanger線程
功能:兩個線程間數據的交換。 原理: 1)線程A調用public V exchange(V dataA)方法,線程A到達同步點,而且在線程B到達同步點前一直等待。 2)線程B調用public V exchange(V dataB)方法,線程B到達同步點。 3)線程A與線程B都達到同步點時,線程將本身的數據傳遞給對方,兩個線程完成了數據的交換了。 舉例: public class ExchangerTest { public static void main(String[] args) { final Exchanger<String> exchanger = new Exchanger<String>(); ExecutorService service = Executors.newFixedThreadPool(2); service.execute(new Runnable() { public void run() { try { String originalData = "dataA"; Thread.sleep(2000); System.out.println("線程" + Thread.currentThread().getName() + "正在把數據[" + originalData + "]傳遞出去..." + " time:" + System.currentTimeMillis()); String exchangedData = exchanger.exchange(originalData); System.out.println("線程" + Thread.currentThread().getName() + "獲取到另外一線程的數據[" + exchangedData + "]" + " time:" + System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } }); service.execute(new Runnable() { public void run() { try { String originalData = "dataB"; Thread.sleep(6000); System.out.println("線程" + Thread.currentThread().getName() + "正在把數據[" + originalData + "]傳遞出去..." + " time:" + System.currentTimeMillis()); String exchangedData = exchanger.exchange(originalData); System.out.println("線程" + Thread.currentThread().getName() + "獲取到另外一線程的數據[" + exchangedData + "]" + " time:" + System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } }); } } 結果: 線程pool-1-thread-1正在把數據[dataA]傳遞出去... time:1506414528645 線程pool-1-thread-2正在把數據[dataB]傳遞出去... time:1506414532645 線程pool-1-thread-2獲取到另外一線程的數據[dataA] time:1506414532645 線程pool-1-thread-1獲取到另外一線程的數據[dataB] time:1506414532645