如何控制多執行緒執行的順序?
先看一段程式碼:
public class TestThread { static Thread thread1=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒1"); } }); static Thread thread2=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒2"); } }); static Thread thread3=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒3"); } }); public static void main(String[] args) { thread1.start(); thread2.start(); thread3.start(); } }
執行結果:
我是執行緒2 我是執行緒3 我是執行緒1
可以看到執行緒的執行順序是隨機的。
查閱資料控制多執行緒執行順序有以下兩種方法:
方法1:呼叫join方法
public class TestThread { static Thread thread1=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒1"); } }); static Thread thread2=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒2"); } }); static Thread thread3=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒3"); } }); public static void main(String[] args) throws Exception{ thread1.start(); thread1.join(); thread2.start(); thread2.join(); thread3.start(); } }
執行結果:
我是執行緒1 我是執行緒2 我是執行緒3
可以看到執行緒按照順序執行。
join方法:讓主執行緒等待子執行緒執行結束後再繼續執行
原理剖析:在main方法中,先是呼叫了t1.start方法,啟動t1執行緒,隨後呼叫t1的join方法,main所在的主執行緒就需要等待t1子執行緒中的run方法執行完成後才能繼續執行,所以主執行緒卡在t2.start方法之前等待t1程式。等t1執行完後,主執行緒重新獲得主動權,繼續執行t2.start和t2.join方法,與t1子執行緒類似,main主執行緒等待t2完成後繼續執行,如此執行下去,join方法就有效的解決了執行順序問題。因為在同一個時間點,各個執行緒是同步狀態。
方法2:Excutors.newSingleThreadExecutor()
public class TestThread { static Thread thread1=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒1"); } }); static Thread thread2=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒2"); } }); static Thread thread3=new Thread(new Runnable() { @Override public void run() { System.out.println("我是執行緒3"); } }); static ExecutorService executorService = Executors.newSingleThreadExecutor(); public static void main(String[] args) throws Exception{ executorService.submit(thread1); executorService.submit(thread2); executorService.submit(thread3); } }
執行結果:
我是執行緒1 我是執行緒2 我是執行緒3
可以看到執行緒按照順序執行。
原理剖析:
利用併發包裡的Excutors的newSingleThreadExecutor產生一個單執行緒的執行緒池,而這個執行緒池的底層原理就是一個先進先出(FIFO)的佇列。程式碼中executor.submit依次添加了123執行緒,按照FIFO的特性,執行順序也就是123的執行結果,從而保證了執行順序。