Semaphore實現信號燈java
lSemaphore能夠維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore能夠控制同時訪問資源的線程個數,例如,實現一個文件容許的併發訪問數。併發
ØSemaphore實現的功能就相似廁全部5個坑,假若有十我的要上廁所,那麼同時能有多少我的去上廁所呢?同時只能有5我的可以佔用,當5我的中的任何一我的讓開後,其中在等待的另外5我的中又有一個能夠佔用了。dom
Ø另外等待的5我的中能夠是隨機得到優先機會,也能夠是按照先來後到的順序得到機會,這取決於構造Semaphore對象時傳入的參數選項。eclipse
l單個信號量的Semaphore對象能夠實現互斥鎖的功能,而且能夠是由一個線程得到了「鎖」,再由另外一個線程釋放「鎖」,這可應用於死鎖恢復的一些場合。工具
管理停車位,一個小的電子設備,實時性強就要semaphore。 關於從這裏開始的各個同步工具例子的代碼,現場編寫的效果還不如拷貝代碼到eclipse中進行解釋的效果直觀和簡潔,這樣能一會兒把全局和總體展示在學員面前。而後再能夠帶着你們一行行地去寫,這樣能夠起到鞏固原理和鍛鍊你們編寫代碼能力和啓發思考的效果。ui
管理停車位,一個小的電子設備,實時性強就要semaphore。
關於從這裏開始的各個同步工具例子的代碼,現場編寫的效果還不如拷貝代碼到eclipse中進行解釋的效果直觀和簡潔,這樣能一會兒把全局和總體展示在學員面前。而後再能夠帶着你們一行行地去寫,這樣能夠起到鞏固原理和鍛鍊你們編寫代碼能力和啓發思考的效果。線程
public class SemaphoreTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); for(int i=0;i<10;i++){ Runnable runnable = new Runnable(){ public void run(){ try { sp.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("線程" + Thread.currentThread().getName() + "進入,當前已有" + (3-sp.availablePermits()) + "個併發"); try { Thread.sleep((long)(Math.random()*10000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程" + Thread.currentThread().getName() + "即將離開"); sp.release(); //下面代碼有時候執行不許確,由於其沒有和上面的代碼合成原子單元 System.out.println("線程" + Thread.currentThread().getName() + "已離開,當前已有" + (3-sp.availablePermits()) + "個併發"); } }; service.execute(runnable); } } }
CyclicBarrier
表示你們彼此等待,你們集合好後纔開始出發,分散活動後又在指定地點集合碰面,這就比如整個公司的人員利用週末時間集體郊遊同樣,先各自從家出發到公司集合後,再同時出發到公園遊玩,在指定地點集合後再同時開始就餐,…。
CountDownLatch
猶如倒計時計數器,調用CountDownLatch對象的countDown方法就將計數器減1,當計數到達0時,則全部等待者或單個等待者開始執行。這直接經過代碼來講明CountDownLatch的做用,這樣學員的理解效果更直接。
能夠實現一我的(也能夠是多我的)等待其餘全部人都來通知他,能夠實現一我的通知多我的的效果,相似裁判一聲口令,運動員同時開始奔跑,或者全部運動員都跑到終點後裁判才能夠公佈結果,用這個功能作百米賽跑的遊戲程序不錯哦!還能夠實現一個計劃須要多個領導都簽字後才能繼續向下實施的狀況。
Exchanger
用於實現兩我的之間的數據交換,每一個人在完成必定的事務後想與對方交換數據,第一個先拿出數據的人將一直等待第二我的拿着數據到來時,才能彼此交換數據。code
Cyclic:循環的,有周期性的
Barrier:障礙物,屏障
Latch:門閂,閂鎖對象
講解CyclicBarrier的功能時,經過輔助畫圖的方式說明,效果會更好。
\ /
\ | /
------------------------三個線程幹完各自的任務,在不一樣的時刻到達集合點後,就能夠接着忙各自的工做去了,再到達新的集合點,再去忙各自的工做,
到達集合點了用CyclicBarrier對象的await方法表示。
/ | \
/ | \
-------------------
爲何幾我的能碰到一塊兒,說白了,就是你們都把手頭這一階段的工做作完了,就能夠碰到一塊兒了。譬如,我下樓等方老師,就是等他手頭工做作完了,他到達了要集合的狀態,就集合了。遊戲
-----------------CyclicBarrier的代碼:--------------------------------- import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { Thread.sleep((long)(Math.random()*10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將到達集合地點1,當前已有" + (cb.getNumberWaiting()+1) + "個已經到達," + (cb.getNumberWaiting()==2?"都到齊了,繼續走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將到達集合地點2,當前已有" + (cb.getNumberWaiting()+1) + "個已經到達," + (cb.getNumberWaiting()==2?"都到齊了,繼續走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將到達集合地點3,當前已有" + (cb.getNumberWaiting() + 1) + "個已經到達," + (cb.getNumberWaiting()==2?"都到齊了,繼續走啊":"正在等候")); cb.await(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } service.shutdown(); } }
-----------------CountdownLatch的代碼:---------------------------------
package cn.itcast.day3.thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountdownLatchTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("線程" + Thread.currentThread().getName() +
"正準備接受命令");
cdOrder.await();
System.out.println("線程" + Thread.currentThread().getName() +
"已接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("線程" + Thread.currentThread().getName() +
"迴應命令處理結果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("線程" + Thread.currentThread().getName() +
"即將發佈命令");
cdOrder.countDown();
System.out.println("線程" + Thread.currentThread().getName() +
"已發送命令,正在等待結果");
cdAnswer.await();
System.out.println("線程" + Thread.currentThread().getName() +
"已收到全部響應結果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}
exchange方法就至關於兩手高高舉着待交換物,等待人家前來交換,一旦人家到來(即人家也執行到exchange方法),則二者立馬完成數據的交換。
import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger exchanger = new Exchanger(); service.execute(new Runnable(){ public void run() { try { String data1 = "zxx"; System.out.println("線程" + Thread.currentThread().getName() + "正在把數據" + data1 +"換出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("線程" + Thread.currentThread().getName() + "換回的數據爲" + data2); }catch(Exception e){ } } }); service.execute(new Runnable(){ public void run() { try { String data1 = "lhm"; System.out.println("線程" + Thread.currentThread().getName() + "正在把數據" + data1 +"換出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("線程" + Thread.currentThread().getName() + "換回的數據爲" + data2); }catch(Exception e){ } } }); } }