多个for语句嵌套执行顺序_阿里真实面试题解析之实现多个线程顺序执行的几种方式...
前幾天有一位同事在阿里一面的時候被問到這么一個多線程問題:如何保證多個線程的順序執(zhí)行。當時他沒有回答上來,所以為了避免大家以后遇到同樣的面試題還是回答不上來,今天我們就來分析解答下這個問題。
問題緣由
由于線程執(zhí)行是靠CPU分時間片來處理的,那么多個線程執(zhí)行的時候,如果不加限制,那么線程的執(zhí)行順序是無法保證的。如下源碼:
public class OrderThreadMain { public static void main(String[] args) { Thread A = new Thread(()->{ System.out.println("A"); }); Thread B = new Thread(()->{ System.out.println("B"); }); Thread C = new Thread(()->{ System.out.println("C"); }); A.start(); B.start(); C.start(); }}A B C三個線程同時啟動,最后的執(zhí)行結果不是每次都順序輸出 A B C,而是每次運行結果都是不一樣的。有可能輸出A B C,有也可能輸出 B A C,是無法保證線程的順序執(zhí)行的。
join方式實現
join方式即使用Thread.join方法來實現。Thread.join含義當前線程需要等待previousThread線程終止之后才從thread.join返回。簡單來說,就是線程沒有執(zhí)行完之前,會一直阻塞在join方法處。
join方式實現方式存在兩種:主線程join和執(zhí)行線程join。下面我們依次來分析一下:
1.主線程join
public class OrderThreadMain { public static void main(String[] args) throws InterruptedException { Thread A = new Thread(()->{ System.out.println("A"); }); Thread B = new Thread(()->{ System.out.println("B"); }); Thread C = new Thread(()->{ System.out.println("C"); }); A.start(); //等待A線程執(zhí)行完在啟動B線程 A.join(); B.start(); //等待B線程執(zhí)行完在啟動C線程 B.join(); C.start(); C.join(); }}//輸出結果://A //B//C上面源碼就是主線程join的實現方式,其原理就是保證執(zhí)行線程執(zhí)行完畢再start后續(xù)線程,從而實現多個線程的順序執(zhí)行。
2.執(zhí)行線程join
package com.example.demo.concurrent;import java.util.concurrent.Executors;public class OrderThreadMain { static class TestThread extends Thread{ private Thread beforeThread; private String str; TestThread(Thread beforeThread, String str){ this.beforeThread = beforeThread; this.str = str; } @Override public void run() { if (beforeThread != null){ try { beforeThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(str); } } public static void main(String[] args) { TestThread A = new TestThread(null, "A"); TestThread B = new TestThread(A, "B"); TestThread C = new TestThread(B, "C"); A.start(); B.start(); C.start(); }}//輸出結果://A //B//C上面源碼就是執(zhí)行線程join的實現方式,其原理就是通過傳入beforeThread(在這個線程執(zhí)行前需要執(zhí)行完的線程對象)來保證多個線程順序執(zhí)行。
Thread.join源碼實現:
public final void join() throws InterruptedException { join(0);}public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { //一直輪訓線程是否執(zhí)行完畢,執(zhí)行完畢則結束,執(zhí)行未完畢一直輪訓 while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }由Thread.join源碼可以知道,Thread.join原理其實很簡單,就是如果線程還未執(zhí)行完成就一直輪訓等待,執(zhí)行完成則結束輪訓,繼續(xù)執(zhí)行后續(xù)代碼。
Executors.newSingleThreadExecutor方式實現
Executors.newSingleThreadExecutor是一種特殊的線程池實現,它是一個單線程的線程池,核心線程數和最大線程數都為1,相當于串行執(zhí)行,所以可以通過它來實現多個線程順序執(zhí)行。
注:如果大家對線程池不是很了解可以閱讀作者之前一篇關于線程池的文章:
阿里P8大佬總結:Java線程池詳解,看了你就懂
public class OrderThreadMain { public static void main(String[] args) { Runnable A = new Runnable() { @Override public void run() { System.out.println("A"); } }; Runnable B = new Runnable() { @Override public void run() { System.out.println("B"); } }; Runnable C = new Runnable() { @Override public void run() { System.out.println("C"); } }; ExecutorService executorService = Executors.newSingleThreadExecutor(); //按順序提交任務 可以保證多個線程按提交順序執(zhí)行 executorService.submit(A); executorService.submit(B); executorService.submit(C); }}//輸出結果://A //B//C上面源碼就是Executors.newSingleThreadExecutor的實現方式,只要保證任務時按順序提交,那么就能保證多個線程任務的順序執(zhí)行。
END
筆者是一位熱愛互聯網、熱愛互聯網技術、熱于分享的年輕人,如果您跟我一樣,我愿意成為您的朋友,分享每一個有價值的知識給您。喜歡作者的同學,點贊+轉發(fā)+關注哦!
點贊+轉發(fā)+關注,私信作者“讀書筆記”即可獲得BAT大廠面試資料、高級架構師VIP視頻課程等高質量技術資料。
BAT等一線互聯網面試資料和VIP高級架構師視頻
總結
以上是生活随笔為你收集整理的多个for语句嵌套执行顺序_阿里真实面试题解析之实现多个线程顺序执行的几种方式...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java程序员常犯的几类错误
- 下一篇: 商城html源码_Java开源商城源码推