日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试必问,如何控制多个线程的执行顺序

發布時間:2024/9/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必问,如何控制多个线程的执行顺序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

面試中經常被遇到一個問題:現在有三個線程,分別執行會打印A,B,C,如何編碼使得三個線程順序執行,即輸出‘ABCABC’,這道題看似簡單,但是如果對多線程不熟悉或者沒有準備還真的不好回答。

下面列舉幾種比較好理解的方法,代碼手工編寫,都已測試

lock和Synchronized都是通過線程間的通信,喚醒指定的線程實現順序執行

1.使用lock

public class Task2Lock {static Lock lock = new ReentrantLock();static int count = 0;static Condition condition1 = lock.newCondition();static Condition condition2 = lock.newCondition();static Condition condition3 = lock.newCondition();/*** 下面的while只是為了控制打印的次數* @param args*/public static void main(String[] args) {Thread tA = new Thread(() -> {while (count < 4) {//先獲取鎖lock.lock();//如果count取余3不等于0,就awaitif (count % 3 != 0) {try {condition1.await();} catch (InterruptedException e) {e.printStackTrace();}}//否則就執行任務并count++,喚醒線程2System.out.println("a");count++;condition2.signal();lock.unlock();}});Thread tB = new Thread(() -> {while (count < 4) {lock.lock();if (count % 3 != 1) {try {condition2.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("l");count++;condition3.signal();lock.unlock();}});Thread tC = new Thread(() -> {while (count < 4) {lock.lock();if (count % 3 != 2) {try {condition3.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("i");count++;condition1.signal();lock.unlock();}});tA.start();tB.start();tC.start();} }

2.使用Synchronized

static Object object = new Object();static int count = 1;public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 2; i++) {synchronized (object) {//注意這里要用while循環while (count != 1) {try {object.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("a");count = 2;object.notifyAll();}}});Thread t2 = new Thread(() -> {for (int i = 0; i < 2; i++) {synchronized (object) {while (count != 2) {try {object.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("b");count = 3;object.notifyAll();}}});Thread t3 = new Thread(() -> {for (int i = 0; i < 2; i++) {synchronized (object) {while (count != 3) {try {object.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("c");count = 1;object.notifyAll();}}});t1.start();t2.start();t3.start();}

還有下面這種寫法,其實就是鎖對象換成了this,我更喜歡上面的,邏輯清晰

public class TaskSynchronized {public static void main(String[] args) {PrintService printService = new PrintService();Thread thread1 = new Thread(() -> {for (int i = 0; i < 2; i++) {printService.printA();}});thread1.setName("A");Thread thread2 = new Thread(() -> {for (int i = 0; i < 2; i++) {printService.printB();}});thread2.setName("B");Thread thread3 = new Thread(() -> {for (int i = 0; i < 2; i++) {printService.printC();}});thread3.setName("C");thread2.start();thread3.start();thread1.start();}/*** 里面的printA,printB,printC都必須加synchronized修飾*/static class PrintService {private int flag = 1;public synchronized void printA() {while (flag != 1) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());flag = 2;this.notifyAll();}public synchronized void printB() {while (flag != 2) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());flag = 3;this.notifyAll();}public synchronized void printC() {while (flag != 3) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());flag = 1;this.notifyAll();}} }

3. 使用join

下面的代碼只能輸出一次ABC,暫時還沒想到如何輸出多次

public class TaskJoin {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(()->{System.out.println("a");});Thread thread2 = new Thread(()->{System.out.println("b");});Thread thread3 = new Thread(()->{System.out.println("c");});//join方法會使得調用線程等待直到thread1結束diethread1.start();thread1.join();thread2.start();thread2.join();thread3.start();} }

join的作用是當前線程等待這個線程結束,底層實現就是循環判斷isAlive(),不斷的await。isAlive()是調用的系統本地方法

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) {while (isAlive()) {wait(0);}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}

4.使用SingleThreadExecutor

public class Task2SingleThreadExecutor {//利用并發包里的Excutors的newSingleThreadExecutor產生一個單線程的線程池,// 而這個線程池的底層原理就是設置核心線程和最大線程都是1static ExecutorService executorService = Executors.newSingleThreadExecutor();public static void main(String[] args) {Thread thread1 = new Thread(()->{System.out.println("a");});Thread thread2 = new Thread(()->{System.out.println("b");});Thread thread3 = new Thread(()->{System.out.println("c");});for (int i = 0; i < 2; i++) {executorService.submit(thread1);executorService.submit(thread2);executorService.submit(thread3);}//作用是關閉線程池,終止線程執行executorService.shutdown();} }

SingleThreadExecutor底層其實就是創建一個核心線程池為1,無界隊列,最大線程為1的線程池

public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

5.使用信號量Semaphore

public class Task2Semaphore {static Semaphore semaphore1 = new Semaphore(1);static Semaphore semaphore2 = new Semaphore(1);static Semaphore semaphore3 = new Semaphore(1);static int count = 0;public static void main(String[] args) {Thread thread1 = new Thread(()->{while (count < 4){try {semaphore1.acquire();} catch (InterruptedException e) {e.printStackTrace();}//這里判斷一次就可以控制執行的次數 System.out.println("a");count++;semaphore2.release();}});Thread thread2 = new Thread(()->{while (count < 4){try {//acquire方法會一直阻塞直到另一個線程釋放他semaphore2.acquire();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("b");count++;semaphore3.release();}});Thread thread3 = new Thread(()->{while (count < 4){try {semaphore3.acquire();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("c");count++;semaphore1.release();}});try {//這里必須先獲取semaphore2,semaphore3,阻止線程2,3運行。也就是必須有線程1先執行,并釋放2的資源semaphore2.acquire();semaphore3.acquire();} catch (InterruptedException e) {e.printStackTrace();}thread2.start();thread1.start();thread3.start();} }

總結

以上是生活随笔為你收集整理的面试必问,如何控制多个线程的执行顺序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。