java并发体系--并发工具类

CyclicBarrier

CyclicBarrier是Java并发工具类之一,它允许一组线程互相等待,直到达到某个公共屏障点(barrier point)。

CyclicBarrier的主要特性包括:

  1. 构造函数:可以通过构造函数指定等待的线程数目。一旦线程数目达到指定值,所有等待的线程将被释放。

  2. await()方法:线程通过调用await()方法进入等待状态,直到所有线程都到达屏障点。

  3. 动作(Action):可以指定在屏障点达到之后,执行的额外动作。

代码示例:

java 复制代码
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {

    public static void main(String[] args) {
        final int numThreads = 3;
        final CyclicBarrier barrier = new CyclicBarrier(numThreads, new Runnable() {
            // 在所有线程到达屏障点之后,执行的额外动作
            @Override
            public void run() {
                System.out.println("所有线程已经到达屏障点,开始执行额外动作");
            }
        });

        for (int i = 0; i < numThreads; i++) {
            final int threadNum = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("线程" + threadNum + "正在执行任务");
                        // 模拟任务执行耗时
                        Thread.sleep(1000);
                        System.out.println("线程" + threadNum + "已经到达屏障点");
                        // 线程到达屏障点,等待其他线程到达
                        barrier.await();
                        System.out.println("线程" + threadNum + "继续执行任务");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

以上代码中,我们创建了一个CyclicBarrier对象,并指定等待的线程数目为3。每个线程在执行任务之后,首先调用await()方法进入等待状态,直到所有线程都到达屏障点。当所有线程到达屏障点之后,CyclicBarrier将执行指定的额外动作(即Runnable对象中的run()方法)。

运行以上代码,输出如下:

线程0正在执行任务
线程1正在执行任务
线程2正在执行任务
线程0已经到达屏障点
线程1已经到达屏障点
线程2已经到达屏障点
所有线程已经到达屏障点,开始执行额外动作
线程0继续执行任务
线程2继续执行任务
线程1继续执行任务

从输出结果可以看出,当所有线程都到达屏障点后,CyclicBarrier执行了额外动作,并且所有线程继续执行任务。

CountDownLatch

CountDownLatch是Java并发编程中的一个工具类,可以让一个或多个线程等待其他线程完成后再继续执行。它的原理是通过一个计数器来实现的,该计数器被初始化为一个正整数,每当一个线程完成自己的任务时,计数器的值会减1,当计数器的值变为0时,等待的线程就会被唤醒,继续执行。

下面是一个使用CountDownLatch的简单示例代码:

java 复制代码
import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        // 创建一个CountDownLatch实例,初始计数器为3
        CountDownLatch latch = new CountDownLatch(3);

        // 创建三个线程
        Thread thread1 = new Thread(new Worker(latch));
        Thread thread2 = new Thread(new Worker(latch));
        Thread thread3 = new Thread(new Worker(latch));

        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();

        try {
            // 等待所有线程完成任务
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 所有线程完成任务后继续执行
        System.out.println("All workers have finished their tasks.");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;

        public Worker(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                // 模拟线程执行任务的耗时
                Thread.sleep((long) (Math.random() * 1000));

                System.out.println("Worker " + Thread.currentThread().getId() + " has finished its task.");

                // 任务完成后计数器减1
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例中,我们创建了一个CountDownLatch实例,初始计数器的值为3。然后创建了三个Worker线程,它们会执行一段耗时的任务,并在任务完成后将计数器的值减1。主线程调用latch.await()方法来等待所有线程完成任务,当计数器的值变为0时,主线程被唤醒,继续执行后续的代码。

每个Worker线程的run()方法中,模拟了执行任务的耗时操作,并在任务完成后调用latch.countDown()方法将计数器的值减1。

运行示例代码,输出结果类似于:

Worker 10 has finished its task.
Worker 11 has finished its task.
Worker 12 has finished its task.
All workers have finished their tasks.

可以看到,三个Worker线程执行完任务后,主线程才继续执行,并输出了"All workers have finished their tasks."。

CyclicBarrier 与CountDownLatch区别

CyclicBarrier和CountDownLatch是Java并发包中的两个类,用于控制并发线程的执行顺序和协作。

CyclicBarrier: CyclicBarrier可以理解为循环栅栏,它可以使一组线程在某个点上等待,直到所有线程都到达这个点,然后所有线程继续执行下去。CyclicBarrier可以被重用,即当线程达到CyclicBarrier后,CyclicBarrier会重置计数,线程可以再次使用它。

CountDownLatch: CountDownLatch则是一种倒计数器,它允许一个或多个线程等待一组操作完成后再继续执行。CountDownLatch的计数器只能被减少,一旦计数器达到0,则等待的线程可以继续执行。

区别:

  1. 功能不同: CyclicBarrier主要用于等待所有线程到达某个点,然后再继续执行;而CountDownLatch主要用于等待一组线程执行完毕,然后再继续执行。

  2. 使用方式不同: CyclicBarrier通过调用await()方法进入等待状态,当所有线程都到达await()点时,才会继续执行。而CountDownLatch通过调用countDown()方法减少计数器的值,线程通过调用await()方法等待计数器值为0。

  3. 可重用性不同: CyclicBarrier可以被重复使用,一旦所有线程到达await()点,计数器会自动重置;而CountDownLatch只能被使用一次,一旦计数器值为0,就不能再次使用。

  4. 等待状态不同: CyclicBarrier可以在等待状态中响应中断,即当线程等待时,可以通过调用interrupt()方法中断线程;而CountDownLatch在等待状态中无法中断线程,只能等待计数器值为0后继续执行。

总结

CyclicBarrier和CountDownLatch都是Java并发编程中常用的同步工具,用于协调多个线程之间的执行顺序和并发操作。

  1. CyclicBarrier: CyclicBarrier是一个同步工具,用于等待一组线程达到某个共同的屏障点,然后再继续执行。它的作用是让一组线程在某个点上等待,直到所有线程都到达这个点后才能继续执行。常用于多线程计算中的数据分片和并行计算。

CyclicBarrier的主要特性和使用方法包括:

  • 创建一个CyclicBarrier对象时,可以指定参与线程的数量。
  • 每个线程调用await()方法之后会被阻塞,直到所有线程都调用了await()方法。
  • 一组线程中的最后一个调用await()方法的线程会触发一个屏障动作,所有被阻塞的线程将被释放。
  • CyclicBarrier可以重复使用,一旦所有线程被释放,它将被重置并可以再次使用。
  1. CountDownLatch: CountDownLatch是一个同步工具,用于等待一个或多个线程完成某个任务后再继续执行。它的作用是让某个线程等待其他线程执行完毕后再继续执行。常用于让某个线程等待其他线程的任务完成。

CountDownLatch的主要特性和使用方法包括:

  • 创建一个CountDownLatch对象时,需要指定计数器的数量,表示需要等待完成的线程数量。
  • 每个线程完成任务后,可以调用countDown()方法来减少计数器的值。
  • 等待线程可以调用await()方法来阻塞等待,直到计数器的值为0。
  • 一旦计数器的值为0,await()方法将返回,等待线程可以继续执行。
相关推荐
电饭叔3 分钟前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student4 分钟前
everyday_question dq20240731
开发语言·arm开发·php
极客先躯8 分钟前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
卑微求AC20 分钟前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
夜月行者29 分钟前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
程序猿小D33 分钟前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
Yvemil738 分钟前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
潘多编程1 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
_阿伟_1 小时前
SpringMVC
java·spring
代码在改了1 小时前
springboot厨房达人美食分享平台(源码+文档+调试+答疑)
java·spring boot