掌握這四種方法,多線程按序執行不再是問題
目錄
- 在子線程中通過join()方法指定順序
- 在主線程中通過join()方法指定順序
- 通過倒數計時器CountDownLatch實現
- 通過創建單一化線程池newSingleThreadExecutor()實現
在子線程中通過join()方法指定順序
通過join()方法使當前線程“阻塞”,等待指定線程執行完畢后繼續執行。
舉例:在線程thread2中,加上一句thread1.join(),其意義在于,當前線程2運行到此行代碼時會進入阻塞狀態,直到線程thread1執行完畢后,線程thread2才會繼續運行,這就保證了線程thread1與線程thread2的運行順序。
public class ThreadJoinDemo {
public static void main(String[] args) throws InterruptedException {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打開冰箱!");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("關上冰箱!");
}
});
//下面三行代碼順序可隨意調整,程序運行結果不受影響,因為我們在子線程中通過“join()方法”已經指定了運行順序。
thread3.start();
thread2.start();
thread1.start();
}
}運行結果:
打開冰箱!
拿出一瓶牛奶!
關上冰箱!在主線程中通過join()方法指定順序
簡單說一下子線程與主線程的區別,子線程指的是發生在Thread內部的代碼,主線程指的是發生在main函數中的代碼,我們可以在main函數中通過join()方法讓主線程阻塞等待以達到指定順序執行的目的。
public class ThreadMainJoinDemo {
public static void main(String[] args) throws InterruptedException {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打開冰箱!");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("關上冰箱!");
}
});
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
}
}輸出結果:
打開冰箱!
拿出一瓶牛奶!
關上冰箱!通過倒數計時器CountDownLatch實現
CountDownLatch通過計數器提供了更靈活的控制,只要檢測到計數器為0當前線程就可以往下執行而不用管相應的thread是否執行完畢。
public class ThreadCountDownLatchDemo {
private static CountDownLatch countDownLatch1 = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打開冰箱!");
countDownLatch1.countDown();
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch1.await();
System.out.println("拿出一瓶牛奶!");
countDownLatch2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch2.await();
System.out.println("關上冰箱!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//下面三行代碼順序可隨意調整,程序運行結果不受影響
thread3.start();
thread1.start();
thread2.start();
}
}輸出結果:
打開冰箱!
拿出一瓶牛奶!
關上冰箱!通過創建單一化線程池newSingleThreadExecutor()實現
單線程化線程池(newSingleThreadExecutor)的優點,串行執行所有任務。
public class ThreadPoolDemo {
static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打開冰箱!");
}
});
final Thread thread2 =new Thread(new Runnable() {
@Override
public void run() {
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("關上冰箱!");
}
});
executorService.submit(thread1);
executorService.submit(thread2);
executorService.submit(thread3);
executorService.shutdown(); //使用完畢記得關閉線程池
}
}輸出結果:
打開冰箱!
拿出一瓶牛奶!
關上冰箱!


























