多线程如何等待所有子线程一起完成任务后再执行主线程

多线程如何等待所有子线程一起完成任务后再执行主线程

1、使用线程类自带的join方法,将子线程加入到主线程,在子线程执行完之后,在执行主线程逻辑。

public static void joinDemo()
        throws InterruptedException
    {
        System.out.println("=========Test with join=====");
        JoinWorker worker1 = new JoinWorker("worker1");
        JoinWorker worker2 = new JoinWorker("worker2");
        worker1.start();
        worker2.start();
        worker1.join();
        worker2.join();
        doSuperWork();
    }


2、使用JDK的并发包中的CountDownLatch类, 使用CountDownLatch,每个线程调用其countDown方法使计数器-1,主线程调用await方法阻塞等待,直到CountDownLatch计数器为0时继续执行,例如
首先,定义子线程


static class CountDownLatchWorker extends Thread
    {
        String workerName;
 
        CountDownLatch latch;
 
        public CountDownLatchWorker(String workerName, CountDownLatch latch)
        {
            this.workerName = workerName;
            this.latch = latch;
        }
 
        public void run()
        {
            System.out.println("Sub Worker " + workerName + " do work begin at "
                               + sdf.format(new Date()));
            new ThreadWaitDemo().doSomeWork();// 做实际工作
            System.out.println("Sub Worker " + workerName + " do work complete at "
                               + sdf.format(new Date()));
            latch.countDown();// 完成之后,计数器减一
 
        }
    }


主线程中调研await方法阻塞等待,直到所有线程完成


public static void countDownLatchDemo()
        throws InterruptedException
    {
        System.out.println("=========Test with CountDownLatch=====");
        CountDownLatch latch = new CountDownLatch(2);
        CountDownLatchWorker worker1 = new CountDownLatchWorker("worker1", latch);
        CountDownLatchWorker worker2 = new CountDownLatchWorker("worker2", latch);
        worker1.start();
        worker2.start();
        //主线程阻塞等待
        latch.await();
        doSuperWork();
    }


3、使用JDK并发包CyclicBarrier,CyclicBarrier类似于CountDownLatch也是个计数器, 不同的是CyclicBarrier的await()方法没被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。 在这之后,如果再次调用 await()方法,计数就又会变成 N-1,新一轮重新开始CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结线程同步计数器俩者区别:
CountDownLatch:一个或者多个线程,等待其他多个线程完成各自的任务之后才能接下来往下执行主线程;
CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行各自的任务,完成最后一个任务之后再执行构造方法第二个参数定义的主线程任务。
对于CountDownLatch来说,重点是“一个线程(多个线程)等待”,而其他的N个线程在完成“某件事情”之后,可以终止,也可以等待。而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须互相等待,然后继续一起执行。

CountDownLatch是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而CyclicBarrier更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 下面是一个简单的java线程池应用的例:public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(5); List<Future<String>> futureList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Future<String> future = executor.submit(() -> { Thread.sleep(1000); return "执行完成"; }); futureList.add(future); } for (Future<String> future : futureList) { System.out.println(future.get()); } System.out.println("所有线程都已完成"); executor.shutdown(); } } ### 回答2: 在Java中,线程池可以通过Java的ExecutorService接口和ThreadPoolExecutor实现类来创建和管理。下面是一个简单的Java线程池的应用示例: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { // 创建具有固定线程数的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 启动3个线程进行工作 executor.submit(new WorkerThread("线程1")); executor.submit(new WorkerThread("线程2")); executor.submit(new WorkerThread("线程3")); // 关闭线程池 executor.shutdown(); // 等待所有线程执行完成后输出一句话 while (!executor.isTerminated()) { // 等待线程池中的任务执行完毕 } System.out.println("所有线程已经执行完成"); } static class WorkerThread implements Runnable { private String threadName; public WorkerThread(String threadName) { this.threadName = threadName; } @Override public void run() { System.out.println("线程" + threadName + "开始执行"); try { // 线程任务 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + threadName + "执行完成"); } } } ``` 该例中,我们创建了一个固定大小为3的线程池。然后通过submit方法提交了3个工作线程(WorkerThread)的任务线程执行。每个工作线程执行任务时,会有2秒的休眠时间模拟实际的工作。 线程在提交了所有任务后,通过调用线程池的shutdown方法来关闭线程池。然后,在线程中通过一个循环,检查线程池中的任务是否全部执行完成,直到线程池中所有任务都已完成,才会输出一句话"所有线程已经执行完成"。 这样就实现了多个线程执行完成后,线程输出一句话的需求。 ### 回答3: Java中的线程池是用来管理和复用线程的。下面是一个简单的使用线程池的例线程需要等待多个线程执行完成之后输出一句话。 ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { // 创建一个固定大小为3的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 创建3个线程并提交到线程执行 for (int i = 0; i < 3; i++) { executor.execute(new MyThread(i)); } // 关闭线程池 executor.shutdown(); // 线程等待所有线程执行完成 while (!executor.isTerminated()) { // 等待线程执行完成 } // 输出一句话 System.out.println("所有线程执行完成"); } static class MyThread implements Runnable { private int id; public MyThread(int id) { this.id = id; } @Override public void run() { System.out.println("线程 " + id + " 开始执行"); // 线程执行任务 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程 " + id + " 执行完成"); } } } ``` 在这个例中,我们使用`Executors.newFixedThreadPool(3)`创建了一个固定大小为3的线程池。然后,我们创建了3个线程,并将它们提交到线程池中执行线程使用`executor.isTerminated()`方法来检查线程池中的所有任务是否都执行完成了。如果没有,则线程等待。 当所有线程执行完成后,线程输出一句话"所有线程执行完成"。 注意:这里的线程池的大小为3,并行执行线程数量也为3,可以通过增加或减少线程池的大小来控制并发度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值