线程的join方法和countdownlatch类

线程的join方法和countdownlatch

线程之间的状态有5种初始、就绪、运行、阻塞、死亡,大家应该都知道,线程在由运行态到阻塞态时有一种方法joinJoin的功能和CountDownLatch类似,可以让所有子线程跑完再执行主线程。下面举例子说明两个的用法

1.线程的join方法,控制执行情况,实现主线程等待子线程。

我们可以拿Dota游戏来举例,在我们玩的时候可以进行单挑(Solo),玩过的应该不陌生,游戏我们认定为主线程,自己和对方定义为子线程,自己和对方的准备也就是加入AB队伍中,加入队伍我们认定是子线程的任务。只有当己方和对方都准备好(进入各自队伍),游戏就会自动开始(对战平台自己触发的)

publicclass ThreadJoinShow {

   privateclass ASubThread implements Runnable{

      private String name;

      public ASubThread(String name) {

         this.name = name;

      }

     

      @Override

      publicvoid run() {

         System.out.println(name+"======正在加入游戏===");

         try {

            Thread.sleep(3000);

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

         System.out.println(name+"======准备好了===");

      }

   }

  

   privateclass BSubThread implements Runnable{

      private String name;

      public BSubThread(String name) {

         this.name = name;

      }

     

      @Override

      publicvoid run() {

         System.out.println(name+"======正在加入游戏===");

         try {

            Thread.sleep(3000);

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

         System.out.println(name+"======准备好了===");

      }

   }

  

   @Test

   publicvoid testNoJoin() throws InterruptedException {

      System.out.println("魔兽初始界面加载请选择阵营====start");

      ASubThread asub = new ASubThread("天灾方选手A");

      BSubThread bsub = new BSubThread("近卫方选手B");

     

      Thread at = new Thread(asub);

      Thread bt = new Thread(bsub);

     

      at.start();

      bt.start();

      System.out.println("魔兽争霸之Dota====进度条走完===进入游戏===end");

      Thread.sleep(10000);//主线程暂停10s是为了防止主线程结束子线程也会跟着结束

   }

  

   @Test

   publicvoid testJoin() throws InterruptedException {

      System.out.println("Join版魔兽初始界面加载请选择阵营====start");

      ASubThread asub = new ASubThread("Join===天灾方选手A");

      BSubThread bsub = new BSubThread("Join===近卫方选手B");

     

      Thread at = new Thread(asub);

      Thread bt = new Thread(bsub);

     

      at.start();

      bt.start();

     

      try {

         at.join();

         bt.join();

      } catch (InterruptedException e) {

         e.printStackTrace();

      }

     

      System.out.println("Join版魔兽争霸之Dota====进度条走完===进入游戏===end");

      Thread.sleep(10000);//主线程暂停10s是为了防止主线程结束子线程也会跟着结束

   }

}

 

执行测试方法console控台打印日志分别如下:

魔兽初始界面加载请选择阵营====start

魔兽争霸之Dota====进度条走完===进入游戏===end

天灾方选手A======正在加入游戏===

近卫方选手B======正在加入游戏===

天灾方选手A======准备好了===

近卫方选手B======准备好了===

 

Join版魔兽初始界面加载请选择阵营====start

Join===天灾方选手A======正在加入游戏===

Join===近卫方选手B======正在加入游戏===

Join===天灾方选手A======准备好了===

Join===近卫方选手B======准备好了===

Join版魔兽争霸之Dota====进度条走完===进入游戏===end

 

由日志可以发现,用了join方法后,主线程会等待子线程执行完,所以正常的游戏流程应该用join版,只有大家都准备好了,才能进入游戏。

 

 

2.CountDownLatch类也可以实现上述的功能,就是等所有子任务都跑完了,主线程再往下执行。

CountDownLatch有两个方法是我们常用的:await();countDown();await()函数用于阻塞当前线程直到CountDownLatch的计数值变为0countDown()方法用于将当前CountDownLatch的计数值减1。举个例子,假设有个女子组合TF girls要参加中戏的艺考,三个人有表演唱歌有表演朗诵有表演舞蹈,只有都通过了,才能拿到中戏的录取通知书,代码如下:                                                                                         public class ThreadCountDownLatchShow {

  

   class SingSongTask implements Runnable{

 

      private CountDownLatch countDownLatch;

      public SingSongTask(CountDownLatch countDownLatch) {

         this.countDownLatch = countDownLatch;

      }

     

      @Override

      publicvoid run() {

         try {

            System.out.println("===A表演唱歌的===start");

            Thread.sleep(3000);

            System.out.println("===A表演唱歌的==表演结束==end");

            countDownLatch.countDown();

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

      }

     

   }

  

   class ReadPoetryTask implements Runnable{

 

      private CountDownLatch countDownLatch;

     

      public ReadPoetryTask(CountDownLatch countDownLatch) {

         this.countDownLatch = countDownLatch;

      }

     

      @Override

      publicvoid run() {

         try {

            System.out.println("===B表演朗读的===start");

            Thread.sleep(6000);

            System.out.println("===B表演朗读的==表演结束==end");

            countDownLatch.countDown();

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

      }

     

   }

  

   class DanceTask implements Runnable{

 

      private CountDownLatch countDownLatch;

     

      public DanceTask(CountDownLatch countDownLatch) {

         this.countDownLatch = countDownLatch;

      }

     

      @Override

      publicvoid run() {

         try {

            System.out.println("===C表演跳舞的===start");

            Thread.sleep(5000);

            System.out.println("===C表演跳舞的==表演结束==end");

            countDownLatch.countDown();

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

      }

     

   }

  

   @Test

   publicvoid testGetZhongxiNotice() throws InterruptedException {

      System.out.println("===TF girls参加中戏考试===");

      CountDownLatch countDownLatch = new CountDownLatch(3);

     

      ExecutorService proctorExec = Executors.newFixedThreadPool(3);

      proctorExec.execute(new SingSongTask(countDownLatch));

      proctorExec.execute(new ReadPoetryTask(countDownLatch));

      proctorExec.execute(new DanceTask(countDownLatch));

      countDownLatch.await();

      proctorExec.shutdown();

      System.out.println("===TF girls参加中戏考试===考试结束===通过===发录取通知书==");

     

   }

}

执行测试方法console控台打印日志分别如下:

===TF girls参加中戏考试===

===A表演唱歌的===start

===B表演朗读的===start

===C表演跳舞的===start

===A表演唱歌的==表演结束==end

===C表演跳舞的==表演结束==end

===B表演朗读的==表演结束==end

===TF girls参加中戏考试===考试结束===通过===发录取通知书==

猜你喜欢

转载自nameethan.iteye.com/blog/2419552