1)semaphore 信號(hào)量 (控制并發(fā)數(shù))
業(yè)務(wù)場(chǎng)景1:假如現(xiàn)在有10個(gè)人去同一家公司面試,但是只有3個(gè)面試官,那么同一時(shí)間只有2個(gè)人面試撬即,當(dāng)3個(gè)人中的任意一個(gè)面試結(jié)束之后端壳,等待的7個(gè)人又會(huì)有一個(gè)人可以去面試。
需求分析:人數(shù)=線程數(shù)?????面試官=資源?????? 正在面試=線程正在執(zhí)行
?????????? ?面試結(jié)束=線程執(zhí)行結(jié)束?????????? 等待面試人數(shù)=線程阻塞
解決方案:信號(hào)量 semaphore
代碼Demo:
public class SemaphoreTest implements Runnable {
private int num;
private Semaphore semaphore;
public SemaphoreTest(int num,Semaphore semaphore){
?????????? ?this.num=num;
??????????? this.semaphore=semaphore;
}
public void run() {
?try {
??? semaphore.acquire();//獲取信號(hào)量許可韩玩,才能進(jìn)入
?? ?System.out.println("面試者"+num+"進(jìn)入房間……");
??? Thread.sleep((long)Math.random()*10000);
?? System.out.println("面試者"+num+"交談中……");
?? Thread.sleep((long)Math.random()*10000);
? System.out.println("面試者"+num+"離開(kāi)房間……");
????? semaphore.release();//釋放信號(hào)量許可
?} catch (InterruptedException e) {
????? e.printStackTrace();
} }
public static void main(String[] args) {
???? final Semaphore s=new Semaphore(3);//并發(fā)數(shù)為3
??? ?ExecutorService threadPool=Executors.newCachedThreadPool();//線程池
?? ?for(int i=0;i<10;i++){
???????? ?threadPool.execute(new SemaphoreTest((i+1),s));
}
??? threadPool.shutdown();
} }
2)Cyclicbarrier? 同步屏障(用于多線程計(jì)算數(shù)據(jù)垒玲,最后合并計(jì)算結(jié)果)
業(yè)務(wù)場(chǎng)景2:公司周末組織去聚餐、首先各自從家里出發(fā)到聚餐地點(diǎn)找颓,當(dāng)所有人全部到齊之后才開(kāi)始吃飯合愈,如果未到齊,到的人就只能等待在那里击狮,直到所有人都到達(dá)之后佛析,才可以一起做事。
案例代碼:
public class CyclicbarrierDemo {
public static void main(String[] args) {
?final CyclicBarrier cb=new CyclicBarrier(3,new Runnable() {
?public void run() {
?????????? System.out.println("吃飯前彪蓬,一起做的事情"); } });
????????????ExecutorService threadPool=Executors.newCachedThreadPool();//線程池
???????? ?for(int i=0;i<3;i++){
??????????? final int user=i+1;
???????????????????????? Runnable r=new Runnable() {
?????????????????????????? public void run() {
??????????????????????????????? try {
???????????????????????????????????? Thread.sleep((long)Math.random()*10000);
????????????????????????????????????? ?System.out.println(user+"到達(dá)聚餐地點(diǎn)寸莫,當(dāng)前已有"+(cb.getNumberWaiting()+1)+"人到達(dá)");
??????????????????????? cb.await();//等待,只有當(dāng)線程都到達(dá)之后档冬,才能往下走
?????????????????????? if(user==1){ System.out.println("人員到齊"); }
????????????????????????? Thread.sleep((long)Math.random()*10000);
??????????????????????? System.out.println(user+"吃完飯储狭,回家……");
?//dosometing
?} catch (Exception e) {
?e.printStackTrace(); } } };
?threadPool.execute(r);
?}
threadPool.shutdown();
?} }
3)Exchanger 線程之間交換數(shù)據(jù)
public class ExchangerDemo {
public static void main(String[] args) {
final Exchangerexchanger=new Exchanger();
?ExecutorService threadPool=Executors.newCachedThreadPool();//線程池
threadPool.execute(new Runnable() {
public void run() { String sc="a";
?try {
String js=exchanger.exchange(sc);//js=b
?} catch (InterruptedException e) { e.printStackTrace(); } } });
?threadPool.execute(new Runnable() {
?public void run() {
String sc="b";
try { String js=exchanger.exchange(sc);//js=a
?} catch (InterruptedException e) { e.printStackTrace(); } } }); } }
執(zhí)行后,連個(gè)線程的數(shù)據(jù)進(jìn)行了交換捣郊。
4)CountDownLatch 倒計(jì)時(shí)器
業(yè)務(wù)場(chǎng)景4:有一個(gè)任務(wù)a辽狈,他需要等待其他幾個(gè)任務(wù)(BCD)都執(zhí)行完畢之后才能來(lái)執(zhí)行這個(gè)任務(wù)。
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch=new CountDownLatch(3);
?new Thread(){
public void run() {
?System.out.println("子任務(wù)B"+Thread.currentThread().getName()+"正在執(zhí)行"); latch.countDown();//倒計(jì)時(shí)減一
}; }.start();
new Thread(){
?public void run() {
System.out.println("子任務(wù)C"+Thread.currentThread().getName()+"正在執(zhí)行"); latch.countDown();//倒計(jì)時(shí)減一
?}; }.start();
new Thread(){
public void run() {
System.out.println("子任務(wù)D"+Thread.currentThread().getName()+"正在執(zhí)行"); latch.countDown();//倒計(jì)時(shí)減一
?}; }.start();
System.out.println("等待3個(gè)任務(wù)執(zhí)行完畢呛牲,"+Thread.currentThread().getName()+"組任務(wù)開(kāi)始執(zhí)行刮萌。");
latch.await();
System.out.println("繼續(xù)執(zhí)行主任務(wù)!");
}
CountDownLatch 與Cyclicbarrier 的區(qū)別:
1)共同點(diǎn):都能夠?qū)崿F(xiàn)線程之間的等待娘扩。
2)不同點(diǎn):
CountDownLatch :1)一般用于某個(gè)線程A等待其他若干線程執(zhí)行完任務(wù)后着茸,它才能執(zhí)行。2)它是不能夠重復(fù)用的琐旁。
Cyclicbarrier :1)一般用于一組線程互相等待涮阔,然后這一組線程同時(shí)執(zhí)行。2)它可以重復(fù)使用灰殴。