多線程同步輔助類

<span style="font-size:18px;">/**
 * 同步輔助類之信號量
 * 允許指定共享資源數量,可以允許指定數量的線程同時訪問資源
 * 與同步的區別在於,同步時,一次只能一個線程訪問資源
 * @author Administrator
 *
 */
public class SemaphoreDemo {
	public static void main(String[] args) {
		final Semaphore semaphore = new Semaphore(2);//指定兩個信號量可同時運行
		System.out.println(Thread.currentThread().getState());
		for (int i = 0; i < 5; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						semaphore.acquire();//獲得一個信號量
						System.out.println(Thread.currentThread().getName() + "來了");
						TimeUnit.SECONDS.sleep(2);
						System.out.println(Thread.currentThread().getName() + "走了");
						semaphore.release();//釋放一個信號量
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
}</span>


/**
 * 同步輔助類之倒計時
 * 初始化CountDownLatch時,可以指定一個整數,按該整數可以進行倒計時
 * 可以控制指定的線程在倒計時未完成時進行等待
 * @author Administrator
 *
 */
public class CountDownLatchDemo {
	public static void main(String[] args) {
		final CountDownLatch countDownLatch = new CountDownLatch(1);//初始倒計時從1開始
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + "預備");
				for (int i = 3; i >= 1; i--) {
					System.out.println(i);
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println(Thread.currentThread().getName() + "開始");
				countDownLatch.countDown();//倒計時減一
			}
		}).start();
		
		
		for (int i = 0; i < 5; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						countDownLatch.await();//等待倒計時爲0纔會向下執行
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "起跑");
				}
			}).start();
		}
	}
}

/**
 * 同步輔助類之循環等待
 * 允許一組線程互相等待,在達到條件後,再同時執行下一步操作
 * 並且條件還可以重用
 * 下列情景爲四個人全部爬到山頂之後再去吃飯,同時吃完飯再去唱歌以此類推
 * @author Administrator
 * 與CountDownLatch倒計時類的區別:
 * 1.CyclicBarrier是一組線程相互都等待
 * 2.CyclicBarrier計數器爲0的時候會自動重置
 */
public class CyclicBarrierDemo {
	public static void main(String[] args) {
		final CyclicBarrier cyclicBarrier = new CyclicBarrier(4);//從4開始倒計時
		for (int i = 0; i < 4; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						System.out.println("準備爬山總人數 : " + cyclicBarrier.getParties());
						System.out.println(Thread.currentThread().getName() + "爬山");
						TimeUnit.SECONDS.sleep(new Random().nextInt(5));
						System.out.println(Thread.currentThread().getName() + "爬到山頂了");
						cyclicBarrier.await();//等待,直到計數器變爲0,每等待一次計數器減1,計數器變爲0後會重置爲4
						
						System.out.println("準備吃飯總人數 : " + cyclicBarrier.getParties());
						System.out.println(Thread.currentThread().getName() + "吃飯");
						TimeUnit.SECONDS.sleep(new Random().nextInt(5));
						System.out.println(Thread.currentThread().getName() + "吃完飯了");
						cyclicBarrier.await();//等待,直到計數器變爲0,每等待一次計數器減1,計數器變爲0後會重置爲4
						
						System.out.println("準備唱歌總人數 : " + cyclicBarrier.getParties());
						System.out.println(Thread.currentThread().getName() + "唱歌");
						TimeUnit.SECONDS.sleep(new Random().nextInt(5));
						System.out.println(Thread.currentThread().getName() + "唱完歌了");
						cyclicBarrier.await();//等待,直到計數器變爲0,每等待一次計數器減1,計數器變爲0後會重置爲4
						
						System.out.println("準備回家總人數 : " + cyclicBarrier.getParties());
						System.out.println(Thread.currentThread().getName() + "回家");
					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (BrokenBarrierException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
}

/**
 * 同步輔助類之交換
 * 可以在一對線程之間交換數據
 * @author Administrator
 *
 */
public class ExchangerDemo {
	public static void main(String[] args) {
		final Exchanger<String> exchanger = new Exchanger<String>();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println(Thread.currentThread().getName() + "賣蘋果");
					TimeUnit.SECONDS.sleep(new Random().nextInt(5));
					String apple = "兩斤蘋果";
					//線程到此阻塞,直到另一個線程執行exchange方法,與該線程交換數據並獲取另一個線程交換的數據
					String money = exchanger.exchange(apple);
					System.out.println(Thread.currentThread().getName() + "賣了" + money);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} 
			}
		}).start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println(Thread.currentThread().getName() + "買蘋果");
					TimeUnit.SECONDS.sleep(new Random().nextInt(5));
					String money = "十塊錢";
					//線程到此阻塞,直到另一個線程執行exchange方法,與該線程交換數據並獲取另一個線程交換的數據
					String apple = exchanger.exchange(money);
					System.out.println(Thread.currentThread().getName() + "買了" + apple);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} 
			}
		}).start();
	}
}


發佈了84 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章