假設有線程1/線程2/線程3,線程3必須在線程1/線程2執行完成之后開始執行,有兩種方式可實現
- Thread類的join方法:使宿主線程阻塞指定時間或者直到寄生線程執行完畢
- CountDownLatch類:指定計數器,當計數器清零即取消阻塞
package com.concurrent.test; import java.util.concurrent.CountDownLatch; import org.junit.Assert; import org.junit.Test; /** * 規定線程的執行順序 */ public class ThreadOrderTest { private long millisUnit = 1000; private int count = 2; class ThreadOrder { /* * join方法使多個線程依次執行 */ public long preserveOrderViaJoin() throws InterruptedException { long startMillis = System.currentTimeMillis(); Thread tmp; for (int i = 0; i < count; i++) { tmp = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(millisUnit); } catch (InterruptedException e) { e.printStackTrace(); } } }, "join-" + i); tmp.start(); tmp.join();//不停地監測線程是否執行完成,執行完成才繼續往下 } return System.currentTimeMillis() - startMillis; } /* * CountdownLatch可同時阻塞多個線程,但它們可並發執行 */ public long preserveOrderViaCountdownLatch() throws InterruptedException { long startMillis = System.currentTimeMillis(); final CountDownLatch countDownLatch = new CountDownLatch(count); for (int i = 0; i < count; i++) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(millisUnit); } catch (InterruptedException e) { e.printStackTrace(); } //只要計數器清零,等待的線程就可以開始執行,於是可以達到並發的效果 countDownLatch.countDown(); } },"countDownLatch-" + i).start(); } countDownLatch.await(); return System.currentTimeMillis() - startMillis; } } @Test public void testPreserveOrderViaJoin() throws InterruptedException { ThreadOrder threadOrder = new ThreadOrder(); Assert.assertEquals(count, threadOrder.preserveOrderViaJoin() / millisUnit); } @Test public void testPreserveOrderViaCountdownLatch() throws InterruptedException { ThreadOrder threadOrder = new ThreadOrder(); Assert.assertEquals(1, threadOrder.preserveOrderViaCountdownLatch() / millisUnit); } }