<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:線程順序執(zhí)行,這么多答案你都答不上來?

          共 43555字,需瀏覽 88分鐘

           ·

          2021-03-11 16:55

          來源:https://cnblogs.com/wenjunwei/p/10573289.html

          一.前言

          本文使用了7中方法實(shí)現(xiàn)在多線程中讓線程按順序運(yùn)行的方法,涉及到多線程中許多常用的方法,不止為了知道如何讓線程按順序運(yùn)行,更是讓讀者對多線程的使用有更深刻的了解。使用的方法如下:

          • [1] 使用線程的join方法
          • [2] 使用主線程的join方法
          • [3] 使用線程的wait方法
          • [4] 使用線程的線程池方法
          • [5] 使用線程的Condition(條件變量)方法
          • [6] 使用線程的CountDownLatch(倒計(jì)數(shù))方法
          • [7] 使用線程的CyclicBarrier(回環(huán)柵欄)方法
          • [8] 使用線程的Semaphore(信號(hào)量)方法

          二.實(shí)現(xiàn)

          我們下面需要完成這樣一個(gè)應(yīng)用場景:

          1.早上;2.測試人員、產(chǎn)品經(jīng)理、開發(fā)人員陸續(xù)的來公司上班;3.產(chǎn)品經(jīng)理規(guī)劃新需求;4.開發(fā)人員開發(fā)新需求功能;5.測試人員測試新功能。

          規(guī)劃需求,開發(fā)需求新功能,測試新功能是一個(gè)有順序的,我們把thread1看做產(chǎn)品經(jīng)理,thread2看做開發(fā)人員,thread3看做測試人員。

          1.使用線程的join方法

          join():是Theard的方法,作用是調(diào)用線程需等待該join()線程執(zhí)行完成后,才能繼續(xù)用下運(yùn)行。

          應(yīng)用場景:當(dāng)一個(gè)線程必須等待另一個(gè)線程執(zhí)行完畢才能執(zhí)行時(shí)可以使用join方法。

          package com.wwj.javabase.thread.order;

          /**
           * @author wwj
           * 通過子程序join使線程按順序執(zhí)行
           */

          public class ThreadJoinDemo {

              public static void main(String[] args) {
                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              thread1.join();
                              System.out.println("開發(fā)人員開發(fā)新需求功能");
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              thread2.join();
                              System.out.println("測試人員測試新功能");
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          2.使用主線程的join方法

          這里是在主線程中使用join()來實(shí)現(xiàn)對線程的阻塞。

          package com.wwj.javabase.thread.order;

          /**
           * @author wwj
           * 通過主程序join使線程按順序執(zhí)行
           */

          public class ThreadMainJoinDemo {

              public static void main(String[] args) throws Exception {

                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("產(chǎn)品經(jīng)理正在規(guī)劃新需求...");
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("開發(fā)人員開發(fā)新需求功能");
                      }
                  });

                  final Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("測試人員測試新功能");
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("產(chǎn)品經(jīng)理來上班了");
                  System.out.println("測試人員來上班了");
                  System.out.println("開發(fā)人員來上班了");
                  thread1.start();
                  //在父進(jìn)程調(diào)用子進(jìn)程的join()方法后,父進(jìn)程需要等待子進(jìn)程運(yùn)行完再繼續(xù)運(yùn)行。
                  System.out.println("開發(fā)人員和測試人員休息會(huì)...");
                  thread1.join();
                  System.out.println("產(chǎn)品經(jīng)理新需求規(guī)劃完成!");
                  thread2.start();
                  System.out.println("測試人員休息會(huì)...");
                  thread2.join();
                  thread3.start();
              }
          }

          運(yùn)行結(jié)果

          產(chǎn)品經(jīng)理來上班了
          測試人員來上班了
          開發(fā)人員來上班了
          開發(fā)人員和測試人員休息會(huì)...
          產(chǎn)品經(jīng)理正在規(guī)劃新需求...
          產(chǎn)品經(jīng)理新需求規(guī)劃完成!
          測試人員休息會(huì)...
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          3.使用線程的wait方法

          wait():是Object的方法,作用是讓當(dāng)前線程進(jìn)入等待狀態(tài),同時(shí),wait()也會(huì)讓當(dāng)前線程釋放它所持有的鎖?!爸钡狡渌€程調(diào)用此對象的 notify() 方法或 notifyAll() 方法”,當(dāng)前線程被喚醒(進(jìn)入“就緒狀態(tài)”)

          notify()和notifyAll():是Object的方法,作用則是喚醒當(dāng)前對象上的等待線程;notify()是喚醒單個(gè)線程,而notifyAll()是喚醒所有的線程。

          wait(long timeout):讓當(dāng)前線程處于“等待(阻塞)狀態(tài)”,“直到其他線程調(diào)用此對象的notify()方法或 notifyAll() 方法,或者超過指定的時(shí)間量”,當(dāng)前線程被喚醒(進(jìn)入“就緒狀態(tài)”)。

          應(yīng)用場景:Java實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的方式。

          package com.wwj.javabase.thread.order;

          /**
           * @author wwj
           */

          public class ThreadWaitDemo {

              private static Object myLock1 = new Object();
              private static Object myLock2 = new Object();

              /**
               * 為什么要加這兩個(gè)標(biāo)識(shí)狀態(tài)?
               * 如果沒有狀態(tài)標(biāo)識(shí),當(dāng)t1已經(jīng)運(yùn)行完了t2才運(yùn)行,t2在等待t1喚醒導(dǎo)致t2永遠(yuǎn)處于等待狀態(tài)
               */

              private static Boolean t1Run = false;
              private static Boolean t2Run = false;
              public static void main(String[] args) {

                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          synchronized (myLock1){
                              System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求...");
                              t1Run = true;
                              myLock1.notify();
                          }
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          synchronized (myLock1){
                              try {
                                  if(!t1Run){
                                      System.out.println("開發(fā)人員先休息會(huì)...");
                                      myLock1.wait();
                                  }
                                  synchronized (myLock2){
                                      System.out.println("開發(fā)人員開發(fā)新需求功能");
                                      myLock2.notify();
                                  }
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          synchronized (myLock2){
                              try {
                                  if(!t2Run){
                                      System.out.println("測試人員先休息會(huì)...");
                                      myLock2.wait();
                                  }
                                  System.out.println("測試人員測試新功能");
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果:這里輸出會(huì)有很多種順序,主要是因?yàn)榫€程進(jìn)入的順序,造成鎖住線程的順序不一致。

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          測試人員先休息會(huì)...
          產(chǎn)品經(jīng)理規(guī)劃新需求...
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          4.使用線程的線程池方法

          JAVA通過Executors提供了四種線程池

          • 單線程化線程池(newSingleThreadExecutor);
          • 可控最大并發(fā)數(shù)線程池(newFixedThreadPool);
          • 可回收緩存線程池(newCachedThreadPool);
          • 支持定時(shí)與周期性任務(wù)的線程池(newScheduledThreadPool)。

          單線程化線程池(newSingleThreadExecutor):優(yōu)點(diǎn),串行執(zhí)行所有任務(wù)。

          submit():提交任務(wù)。

          shutdown():方法用來關(guān)閉線程池,拒絕新任務(wù)。

          應(yīng)用場景:串行執(zhí)行所有任務(wù)。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會(huì)有一個(gè)新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。

          package com.wwj.javabase.thread.order;

          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;

          /**
           * @author wwj
           * 通過SingleThreadExecutor讓線程按順序執(zhí)行
           */

          public class ThreadPoolDemo {

              static ExecutorService executorService = Executors.newSingleThreadExecutor();

              public static void main(String[] args) throws Exception {

                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("開發(fā)人員開發(fā)新需求功能");
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("測試人員測試新功能");
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("產(chǎn)品經(jīng)理來上班了");
                  System.out.println("測試人員來上班了");
                  System.out.println("開發(fā)人員來上班了");
                  System.out.println("領(lǐng)導(dǎo)吩咐:");
                  System.out.println("首先,產(chǎn)品經(jīng)理規(guī)劃新需求...");
                  executorService.submit(thread1);
                  System.out.println("然后,開發(fā)人員開發(fā)新需求功能...");
                  executorService.submit(thread2);
                  System.out.println("最后,測試人員測試新功能...");
                  executorService.submit(thread3);
                  executorService.shutdown();
              }
          }

          運(yùn)行結(jié)果

          早上:
          產(chǎn)品經(jīng)理來上班了
          測試人員來上班了
          開發(fā)人員來上班了
          領(lǐng)導(dǎo)吩咐:
          首先,產(chǎn)品經(jīng)理規(guī)劃新需求...
          然后,開發(fā)人員開發(fā)新需求功能...
          最后,測試人員測試新功能...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          5.使用線程的Condition(條件變量)方法

          Condition(條件變量):通常與一個(gè)鎖關(guān)聯(lián)。需要在多個(gè)Contidion中共享一個(gè)鎖時(shí),可以傳遞一個(gè)Lock/RLock實(shí)例給構(gòu)造方法,否則它將自己生成一個(gè)RLock實(shí)例。

          • Condition中**await()**方法類似于Object類中的wait()方法。
          • Condition中**await(long time,TimeUnit unit)**方法類似于Object類中的wait(long time)方法。
          • Condition中**signal()**方法類似于Object類中的notify()方法。
          • Condition中**signalAll()**方法類似于Object類中的notifyAll()方法。

          應(yīng)用場景:Condition是一個(gè)多線程間協(xié)調(diào)通信的工具類,使得某個(gè),或者某些線程一起等待某個(gè)條件(Condition),只有當(dāng)該條件具備( signal 或者 signalAll方法被帶調(diào)用)時(shí) ,這些等待線程才會(huì)被喚醒,從而重新爭奪鎖。

          package com.wwj.javabase.thread.order;

          import java.util.concurrent.locks.Condition;
          import java.util.concurrent.locks.Lock;
          import java.util.concurrent.locks.ReentrantLock;

          /**
           * @author wwj
           * 使用Condition(條件變量)實(shí)現(xiàn)線程按順序運(yùn)行
           */

          public class ThreadConditionDemo {

              private static Lock lock = new ReentrantLock();
              private static Condition condition1 = lock.newCondition();
              private static Condition condition2 = lock.newCondition();

              /**
               * 為什么要加這兩個(gè)標(biāo)識(shí)狀態(tài)?
               * 如果沒有狀態(tài)標(biāo)識(shí),當(dāng)t1已經(jīng)運(yùn)行完了t2才運(yùn)行,t2在等待t1喚醒導(dǎo)致t2永遠(yuǎn)處于等待狀態(tài)
               */

              private static Boolean t1Run = false;
              private static Boolean t2Run = false;

              public static void main(String[] args) {

                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          lock.lock();
                          System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                          t1Run = true;
                          condition1.signal();
                          lock.unlock();
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          lock.lock();
                          try {
                              if(!t1Run){
                                  System.out.println("開發(fā)人員先休息會(huì)...");
                                  condition1.await();
                              }
                              System.out.println("開發(fā)人員開發(fā)新需求功能");
                              t2Run = true;
                              condition2.signal();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          lock.unlock();
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          lock.lock();
                          try {
                              if(!t2Run){
                                  System.out.println("測試人員先休息會(huì)...");
                                  condition2.await();
                              }
                              System.out.println("測試人員測試新功能");
                              lock.unlock();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果:這里輸出會(huì)有很多種順序,主要是因?yàn)榫€程進(jìn)入的順序,造成鎖住線程的順序不一致

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          測試人員先休息會(huì)...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          6.使用線程的CountDownLatch(倒計(jì)數(shù))方法

          CountDownLatch:位于java.util.concurrent包下,利用它可以實(shí)現(xiàn)類似計(jì)數(shù)器的功能。

          應(yīng)用場景:比如有一個(gè)任務(wù)C,它要等待其他任務(wù)A,B執(zhí)行完畢之后才能執(zhí)行,此時(shí)就可以利用CountDownLatch來實(shí)現(xiàn)這種功能了。

          package com.wwj.javabase.thread.order;

          import java.util.concurrent.CountDownLatch;

          /**
           * @author wwj
           * 通過CountDownLatch(倒計(jì)數(shù))使線程按順序執(zhí)行
           */

          public class ThreadCountDownLatchDemo {

              /**
               * 用于判斷線程一是否執(zhí)行,倒計(jì)時(shí)設(shè)置為1,執(zhí)行后減1
               */

              private static CountDownLatch c1 = new CountDownLatch(1);

              /**
               * 用于判斷線程二是否執(zhí)行,倒計(jì)時(shí)設(shè)置為1,執(zhí)行后減1
               */

              private static CountDownLatch c2 = new CountDownLatch(1);

              public static void main(String[] args) {
                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                          //對c1倒計(jì)時(shí)-1
                          c1.countDown();
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              //等待c1倒計(jì)時(shí),計(jì)時(shí)為0則往下運(yùn)行
                              c1.await();
                              System.out.println("開發(fā)人員開發(fā)新需求功能");
                              //對c2倒計(jì)時(shí)-1
                              c2.countDown();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              //等待c2倒計(jì)時(shí),計(jì)時(shí)為0則往下運(yùn)行
                              c2.await();
                              System.out.println("測試人員測試新功能");
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          7.使用CyclicBarrier(回環(huán)柵欄)實(shí)現(xiàn)線程按順序運(yùn)行

          CyclicBarrier(回環(huán)柵欄):通過它可以實(shí)現(xiàn)讓一組線程等待至某個(gè)狀態(tài)之后再全部同時(shí)執(zhí)行。叫做回環(huán)是因?yàn)楫?dāng)所有等待線程都被釋放以后,CyclicBarrier可以被重用。我們暫且把這個(gè)狀態(tài)就叫做barrier,當(dāng)調(diào)用await()方法之后,線程就處于barrier了。

          應(yīng)用場景:公司組織春游,等待所有的員工到達(dá)集合地點(diǎn)才能出發(fā),每個(gè)人到達(dá)后進(jìn)入barrier狀態(tài)。都到達(dá)后,喚起大家一起出發(fā)去旅行。

          package com.wwj.javabase.thread.order;

          import java.util.concurrent.BrokenBarrierException;
          import java.util.concurrent.CyclicBarrier;

          /**
           * @author wwj
           * 使用CyclicBarrier(回環(huán)柵欄)實(shí)現(xiàn)線程按順序運(yùn)行
           */

          public class CyclicBarrierDemo {

              static CyclicBarrier barrier1 = new CyclicBarrier(2);
              static CyclicBarrier barrier2 = new CyclicBarrier(2);

              public static void main(String[] args) {

                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                              //放開柵欄1
                              barrier1.await();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          } catch (BrokenBarrierException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              //放開柵欄1
                              barrier1.await();
                              System.out.println("開發(fā)人員開發(fā)新需求功能");
                              //放開柵欄2
                              barrier2.await();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          } catch (BrokenBarrierException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  final Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              //放開柵欄2
                              barrier2.await();
                              System.out.println("測試人員測試新功能");
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          } catch (BrokenBarrierException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          8.使用Sephmore(信號(hào)量)實(shí)現(xiàn)線程按順序運(yùn)行

          Sephmore(信號(hào)量):Semaphore是一個(gè)計(jì)數(shù)信號(hào)量,從概念上將,Semaphore包含一組許可證,如果有需要的話,每個(gè)acquire()方法都會(huì)阻塞,直到獲取一個(gè)可用的許可證,每個(gè)release()方法都會(huì)釋放持有許可證的線程,并且歸還Semaphore一個(gè)可用的許可證。然而,實(shí)際上并沒有真實(shí)的許可證對象供線程使用,Semaphore只是對可用的數(shù)量進(jìn)行管理維護(hù)。

          acquire():當(dāng)前線程嘗試去阻塞的獲取1個(gè)許可證,此過程是阻塞的,當(dāng)前線程獲取了1個(gè)可用的許可證,則會(huì)停止等待,繼續(xù)執(zhí)行。

          release():當(dāng)前線程釋放1個(gè)可用的許可證。

          應(yīng)用場景:Semaphore可以用來做流量分流,特別是對公共資源有限的場景,比如數(shù)據(jù)庫連接。假設(shè)有這個(gè)的需求,讀取幾萬個(gè)文件的數(shù)據(jù)到數(shù)據(jù)庫中,由于文件讀取是IO密集型任務(wù),可以啟動(dòng)幾十個(gè)線程并發(fā)讀取,但是數(shù)據(jù)庫連接數(shù)只有10個(gè),這時(shí)就必須控制最多只有10個(gè)線程能夠拿到數(shù)據(jù)庫連接進(jìn)行操作。這個(gè)時(shí)候,就可以使用Semaphore做流量控制。

          package com.wwj.javabase.thread.order;

          import java.util.concurrent.Semaphore;
          /**
           * @author wwj
           * 使用Sephmore(信號(hào)量)實(shí)現(xiàn)線程按順序運(yùn)行
           */

          public class SemaphoreDemo {
              private static Semaphore semaphore1 = new Semaphore(1);
              private static Semaphore semaphore2 = new Semaphore(1);
              public static void main(String[] args) {
                  final Thread thread1 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          System.out.println("產(chǎn)品經(jīng)理規(guī)劃新需求");
                          semaphore1.release();
                      }
                  });

                  final Thread thread2 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              semaphore1.acquire();
                              System.out.println("開發(fā)人員開發(fā)新需求功能");
                              semaphore2.release();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  Thread thread3 = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          try {
                              semaphore2.acquire();
                              thread2.join();
                              semaphore2.release();
                              System.out.println("測試人員測試新功能");
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  });

                  System.out.println("早上:");
                  System.out.println("測試人員來上班了...");
                  thread3.start();
                  System.out.println("產(chǎn)品經(jīng)理來上班了...");
                  thread1.start();
                  System.out.println("開發(fā)人員來上班了...");
                  thread2.start();
              }
          }

          運(yùn)行結(jié)果

          早上:
          測試人員來上班了...
          產(chǎn)品經(jīng)理來上班了...
          開發(fā)人員來上班了...
          產(chǎn)品經(jīng)理規(guī)劃新需求
          開發(fā)人員開發(fā)新需求功能
          測試人員測試新功能

          總結(jié)

          看完了這么多種方法,是不是對多線程有了更深入的了解呢?不妨自己試試吧(代碼拷貝均可運(yùn)行)

          使用的場景還有很多,根據(jù)開發(fā)需求場景,選擇合適的方法,達(dá)到事半功倍的效果。

          面試絕對不能寫的代碼片段

          說實(shí)話!你知道 Java 中的回調(diào)機(jī)制嗎?

          《吃透 MQ 系列》之核心基礎(chǔ)篇

          介紹一款 API 敏捷開發(fā)工具,太爽了!

          一款 Java 開源的 Spring Boot 即時(shí)通訊 IM 聊天系統(tǒng)

          趕快試試 IDEA 解決 Maven 依賴沖突的高能神器!

          瀏覽 51
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲三级网站在线观看 | 毛片一区77 | 国产女人操逼打咆视频 | 国产亚洲欧美精品久久久久久 | 中文字幕人妻无码蜜桃 |