假設有線程1/線程2/線程3,線程3必須在線程1/線程2執行完成之后開始執行,有兩種方式可實現
- Thread類的join方法:使宿主線程阻塞指定時間或者直到寄生線程執行完畢
- CountDownLatch類:指定計數器,當計數器清零即取消阻塞
import java.util.concurrent.CountDownLatch; import org.junit.Assert; import org.junit.Test; /** * @Description: 規定線程次序的方法 */ public class ThreadOrderTest { private long millisUnit = 1000; private int count = 2; class ThreadOrder { /** * join方法使多個線程依次執行 * * @return * @throws InterruptedException */ 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可同時阻塞多個線程,但它們可並發執行 * * @return * @throws InterruptedException */ 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); } }
