CountDawnLatch
用 CountDownLatch 控制多個線程同時開始
- 思路: 通過主線程設置 CountDawnLatch 值爲 1,其他線程設置 await(),等待count=0, 主線程執行 count.countDown(),喚醒所有等待線程
/**
* 用 CountDownLatch 控制多個線程同時開始
* 思路: 通過主線程設置 CountDawnLatch 值爲 1,其他線程設置 await(),等待count=0, 主線程執行 count.countDown(),喚醒所有等待線程
*
*/
public class CountDawnLatchDemo
{
public static void main(String[] args) throws InterruptedException
{
CountDownLatch count = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run()
{
try
{
count.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("thread1 結束");
}
}).start();
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
count.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
count.countDown();
System.out.println("thread2 結束");
}
}).start();
Thread.sleep(3000);
count.countDown();
}
}
CyclicBarrier
*CyclicBarrier 控制多個線程同時開始
- 思路:CyclicBarrier 設置柵欄解鎖條件爲 n,啓動n個線程,每個線程調用 await(), 直到第n個線程進入柵欄時,才解鎖喚醒所有線程
- CyclicBarrier還可以設置解鎖後的新任務 , 會選擇其中一個線程去執行方法Runable(). 一般選擇最後一個進入柵欄的線程
/**
* CyclicBarrier 控制多個線程同時開始
* 思路:CyclicBarrier 設置柵欄解鎖條件爲 n,啓動n個線程,每個線程調用 await(), 直到第n個線程進入柵欄時,才解鎖喚醒所有線程
* CyclicBarrier還可以設置解鎖後的新任務 , 會選擇其中一個線程去執行方法Runable(). 一般選擇最後一個進入柵欄的線程
*
*/
public class CyclicBarrierDemo
{
public static void main(String[] args) throws InterruptedException, BrokenBarrierException
{
CyclicBarrier cb = new CyclicBarrier(3, new Runnable()
{
@Override
public void run()
{
System.out.println("被選擇處理 action的線程是: " + Thread.currentThread().getName());
System.out.println("action after barrier ");
}
});
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
cb.await(); // 到達屏障,當前線程被阻塞,只有所有需要的線程數量到達屏障後,屏障纔會解除,執行
}
catch (InterruptedException | BrokenBarrierException e)
{
e.printStackTrace();
}
System.out.println("thread 1 await over");
}
}, "thread1").start();
Thread.sleep(3000);
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
cb.await();
Thread.sleep(7000);
System.out.println("當前阻塞的線程數:" + cb.getNumberWaiting());
}
catch (InterruptedException | BrokenBarrierException e)
{
e.printStackTrace();
}
System.out.println("thread 2 await over");
}
}, "thread2");
t2.start();
Thread.sleep(1000);
System.out.println("main: 當前阻塞的線程數:" + cb.getNumberWaiting());
t2.interrupt(); // t2線程處於 await() 時被中斷,導致柵欄失效,所有正在柵欄處等待的線程拋出BrokenBarrier異常(t2拋出 中斷異常),執行後續的操作
Thread.sleep(100);
System.out.println("main: 當前阻塞的線程數:" + cb.getNumberWaiting());
// 拋出 BrokenBarrierException 異常,終止程序
cb.await();
System.out.println("main over");
}
}
public class CyclicBarrierDemo3
{
public static void main(String[] args) throws InterruptedException, BrokenBarrierException
{
CyclicBarrier cb = new CyclicBarrier(3);
new Thread(new Runner(cb)).start();
Thread.sleep(100);
new Thread(new Runner(cb)).start();
Thread.sleep(2100);
System.out.println(cb.getNumberWaiting()); // 此時線程0 、1 都在處於 await()狀態 , 1s 後線程 0 檢測到超時,拋出 TimeoutException ,柵欄解除,線程 1 拋出 BrokenBarrierException
Thread.sleep(4000);
System.out.println(cb.getNumberWaiting());
cb.await(); // main 線程拋出 BrokenBarrierException
System.out.println("main over");
}
static class Runner implements Runnable
{
private CyclicBarrier cb;
public Runner(CyclicBarrier cb)
{
this.cb = cb;
}
@Override
public void run()
{
try
{
System.out.println(Thread.currentThread().getName() + "進入");
Thread.sleep(2000);
cb.await(1000, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (BrokenBarrierException e)
{
System.out.println("線程" + Thread.currentThread().getName() + "拋出BrokenBarrierException");
e.printStackTrace();
}
catch (TimeoutException e)
{
System.out.println("線程" + Thread.currentThread().getName() + "拋出TimeoutException");
e.printStackTrace();
}
System.out.println("線程" + Thread.currentThread().getName() + " 執行任務");
}
}
}