等待某(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

 

运行结果:

等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)..._第1张图片

 

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

 

执行结果:

等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)..._第2张图片

 

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

 

 
   

 

转载于:https://www.cnblogs.com/cici20166/p/6436180.html

你可能感兴趣的:(等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)...)