zoukankan      html  css  js  c++  java
  • 等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)

    1.main线程中先调用threadA.join() ,再调用threadB.join()实现A->B->main线程的执行顺序

     调用threadA.join()时,main线程会挂起,等待threadA执行完毕返回后再执行,到执行threadB.join()时再挂起,待threadB执行完毕返回继续执行main

    使用场景:线程B依赖线程A的计算结果的场景

    package concurrency;
    
    public class JoinTest {
        public static void main(String[] args) throws InterruptedException{
            Thread threadA = new Thread(new JoinJob(),"thread-A");
            Thread threadB = new Thread(new JoinJob(),"thread-B");
            threadB.start();
            threadA.start();
            threadA.join();
            threadB.join();
            
            System.out.println("main ending...");
        }
    }
    
    class JoinJob implements Runnable{
        
        @Override
        public void run() {
            System.err.println(Thread.currentThread().getName() + " starting...");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " ending...");
            
        }
        
    }
    View Code

    运行结果

    2.CountDownLatch

    使用场景:多线程数据计算时需要先分几个线程计算第一步骤的数据,再合并一个线程计算第二步

     1 package concurrency;
     2 
     3 import java.util.concurrent.CountDownLatch;
     4 
     5 public class CountDownLatchTest {
     6     static CountDownLatch c = new CountDownLatch(6);//如果count大于实际线程数,c.await()会一直等待
     7     
     8     public static void main(String[] args) throws InterruptedException{
     9         for (int i = 0; i < c.getCount()/2; i++) {
    10             new Thread(new CountDownJob(c)).start();
    11             new Thread(new CountDownLatchJob2(c)).start();
    12             
    13         }
    14         
    15         System.out.println("waiting " + c.getCount() + " subthread doing");
    16         c.await();//await()会等待c的count值为0,才继续往下执行
    17         System.out.println("all subthread done!");
    18         System.out.println(Thread.currentThread().getName() + " done!");
    19     }
    20 }
    21 
    22 class CountDownJob implements Runnable{
    23     CountDownLatch cDownLatch;
    24     
    25     public CountDownJob(CountDownLatch cDownLatch) {
    26         super();
    27         this.cDownLatch = cDownLatch;
    28     }
    29 
    30     @Override
    31     public void run() {
    32         try {
    33             System.out.println(Thread.currentThread().getName() + " is doing something...");
    34             Thread.sleep(3000);
    35             cDownLatch.countDown();//线程结束时cDownLatch-1
    36         } catch (InterruptedException e) {
    37             e.printStackTrace();
    38         }
    39     
    40     }
    41     
    42 }
    43 class CountDownLatchJob2 implements Runnable{
    44     CountDownLatch cDownLatch;
    45     
    46     public CountDownLatchJob2(CountDownLatch cDownLatch) {
    47         super();
    48         this.cDownLatch = cDownLatch;
    49     }
    50     @Override
    51     public void run() {
    52         try {
    53             Thread.sleep(1000);
    54         } catch (InterruptedException e) {
    55             System.err.println("thread sleep exception");
    56         }
    57         System.out.println(Thread.currentThread().getName() + " is doing something");
    58         cDownLatch.countDown();//线程结束时cDownLatch-1
    59     }
    60     
    61 }
    View Code

    运行结果:

    3.可循环使用的同步屏障CyclicBarrier

    使用场景:多线程计算数据,等待全部线程执行完阶段一的工作之后,再执行后面的阶段工作

     1 package concurrency;
     2 
     3 import java.util.concurrent.BrokenBarrierException;
     4 import java.util.concurrent.CyclicBarrier;
     5 
     6 public class CyclicBarrierTest {
     7     public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
     8         CyclicBarrier cBarrier = new CyclicBarrier(6);
     9         //CyclicBarrier 提供另一个构造函数传入所有线程执行完后需要执行的runnable
    10 //        CyclicBarrier cBarrier = new CyclicBarrier(6, new Runnable() {
    11 //            
    12 //            @Override
    13 //            public void run() {
    14 //                System.out.println("doing something after all threads done.");
    15 //            }
    16 //        });
    17         for (int i = 0; i < cBarrier.getParties()/2; i++) {
    18             new Thread(new CyclicBarrierJob1(cBarrier)).start();
    19             new Thread(new CyclicBarrierJob2(cBarrier)).start();
    20         }
    21         //CyclicBarrier 可以重置再次使用,如计算发生错误时可以重置计数器,并让线程重新执行一次。
    22         //而CountDownLatch只可以使用一次
    23         //cBarrier.reset();
    24     }
    25 }
    26 
    27 class CyclicBarrierJob1 implements Runnable {
    28     CyclicBarrier cBarrier;
    29     
    30     public CyclicBarrierJob1(CyclicBarrier cBarrier) {
    31         super();
    32         this.cBarrier = cBarrier;
    33     }
    34 
    35     public void run() {
    36         System.out.println(Thread.currentThread().getName() + " finished phase1");
    37         try {
    38             cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
    39         } catch (InterruptedException e) {
    40             System.err.println("interrupted!");
    41         } catch (BrokenBarrierException e) {
    42             System.err.println("broken barrier!");
    43         }
    44         
    45         System.out.println(Thread.currentThread().getName() + " start phase2");
    46     }
    47 }
    48 class CyclicBarrierJob2 implements Runnable {
    49     CyclicBarrier cBarrier;
    50     
    51     public CyclicBarrierJob2(CyclicBarrier cBarrier) {
    52         super();
    53         this.cBarrier = cBarrier;
    54     }
    55     
    56     public void run() {
    57         System.out.println(Thread.currentThread().getName() + " finished phase1");
    58         try {
    59             cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
    60         } catch (InterruptedException e) {
    61             System.err.println("interrupted!");
    62         } catch (BrokenBarrierException e) {
    63             System.err.println("broken barrier!");
    64         }
    65         System.out.println(Thread.currentThread().getName() + " start phase2");
    66         
    67     }
    68 }
    View Code

    执行结果:

    4.可控制并发线程数的信号量Semaphore

    使用场景:控制同时访问特定资源的线程数量

     1 package concurrency;
     2 
     3 import java.util.concurrent.Semaphore;
     4 
     5 public class SemaphoreTest {
     6     public static void  main(String[] args) {
     7         final Semaphore semaphore = new Semaphore(3);//限制可以同时访问资源的线程数是10个
     8         
     9         for (int i = 0; i < 12; i++) {//新建30个线程
    10             new Thread(new Runnable() {
    11                 
    12                 @Override
    13                 public void run() {
    14                     try {
    15                         semaphore.acquire();//获取到许可证才可以访问资源
    16                         System.out.println("accessing the database ..");
    17                         Thread.sleep(3000);
    18                         semaphore.release();//资源访问结束之后释放许可证
    19                     } catch (InterruptedException e) {
    20                         System.out.println("interrupted!");
    21                     }
    22                     
    23                 }
    24             }).start();
    25         }
    26         
    27     }
    28 }
    View Code

    
    
    
  • 相关阅读:
    备战noip week1
    20200820校测
    UVA 11419 SAM I AM
    需求沟通技巧
    ReentrantLock和ReentrantReadWriteLock对比
    线程池浅析
    常用设计模式之单例模式
    java开发3~5年工作经验面试题
    2019计划
    Linux系统安装Tomcat
  • 原文地址:https://www.cnblogs.com/cici20166/p/6436180.html
Copyright © 2011-2022 走看看