Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

介绍

本篇文章主要讲解Java并发编程中的三种常用同步工具:CountDownLatch、CyclicBarrier和Semaphore。这三种工具都可以用于协调线程的执行,但实现的方式有所不同。

  • CountDownLatch:用于等待多个线程执行完毕后再执行某个操作。
  • CyclicBarrier:用于等待多个线程到达某个屏障点后再同时执行某个操作。
  • Semaphore:用于控制同时访问某个资源的线程数量。

CountDownLatch

CountDownLatch是一个同步工具类,用于等待多个线程完成一定的操作后再进行下一步操作。它的原理是维护一个计数器,初始化时需要指定计数器的值,在每个线程完成一定操作后,计数器的值减1,当计数器的值减到0时,表示所有线程已完成操作,等待的线程可以继续执行。

下面是一个简单的示例,我们使用CountDownLatch来等待两个线程执行完毕后计算它们的和:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchExample {

    public static void main(String[] args) throws Exception {
        int nThreads = 2;
        CountDownLatch countDownLatch = new CountDownLatch(nThreads);

        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);

        for (int i = 1; i <= nThreads; i++) {
            executorService.submit(new Worker(i, countDownLatch));
        }

        countDownLatch.await();

        System.out.println("All workers have finished the job");
    }

    static class Worker implements Runnable {

        private int id;
        private CountDownLatch countDownLatch;

        public Worker(int id, CountDownLatch countDownLatch) {
            this.id = id;
            this.countDownLatch = countDownLatch;
        }

        public void run() {
            System.out.printf("Worker %d starts to work\n", id);

            try {
                Thread.sleep(2000);  // 模拟完成某些操作
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            System.out.printf("Worker %d has finished the job\n", id);

            countDownLatch.countDown();
        }
    }
}

运行结果如下:

Worker 1 starts to work
Worker 2 starts to work
Worker 1 has finished the job
Worker 2 has finished the job
All workers have finished the job

CyclicBarrier

CyclicBarrier也是一个同步工具类,和CountDownLatch不同的是,它可以多次等待。CyclicBarrier能够等待多个线程到达同一个屏障点后再继续执行。它的原理是维护一个计数器和一个barrierAction,在每个线程完成一定操作后,计数器的值减1,当计数器的值减到0时,执行barrierAction,并重置计数器的值,等待的线程可以继续执行。

下面是一个简单的示例,我们使用CyclicBarrier来等待三个线程到达同一个屏障点后继续执行:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {

    public static void main(String[] args) {
        int parties = 3;

        CyclicBarrier cyclicBarrier = new CyclicBarrier(parties, () -> {
            System.out.println("All parties have arrived at the barrier, continue to execute");
        });

        new Worker(1, cyclicBarrier).start();
        new Worker(2, cyclicBarrier).start();
        new Worker(3, cyclicBarrier).start();
    }

    static class Worker extends Thread {

        private int id;
        private CyclicBarrier cyclicBarrier;

        public Worker(int id, CyclicBarrier cyclicBarrier) {
            this.id = id;
            this.cyclicBarrier = cyclicBarrier;
        }

        public void run() {
            System.out.printf("Worker %d starts to work\n", id);

            try {
                Thread.sleep(2000);  // 模拟完成某些操作
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            System.out.printf("Worker %d has arrived at the barrier\n", id);

            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }

            System.out.printf("Worker %d continues to execute\n", id);
        }
    }
}

运行结果如下:

Worker 1 starts to work
Worker 2 starts to work
Worker 3 starts to work
Worker 1 has arrived at the barrier
Worker 2 has arrived at the barrier
Worker 3 has arrived at the barrier
All parties have arrived at the barrier, continue to execute
Worker 2 continues to execute
Worker 1 continues to execute
Worker 3 continues to execute

Semaphore

Semaphore是一个同步工具类,用于控制同时访问某个资源的线程数量。它的原理是维护一个计数器,初始化时需要指定计数器的值,线程想要访问该资源时需要获取许可,如果许可数量大于0,则可以获取许可并继续执行,许可数量减1;否则线程必须等待其他线程释放许可。

下面是一个简单的示例,我们使用Semaphore来控制同时访问某个资源的线程数量:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    public static void main(String[] args) {
        int nThreads = 10;
        Semaphore semaphore = new Semaphore(3);

        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);

        for (int i = 0; i < nThreads; i++) {
            executorService.submit(new Worker(i, semaphore));
        }
    }

    static class Worker implements Runnable {

        private int id;
        private Semaphore semaphore;

        public Worker(int id, Semaphore semaphore) {
            this.id = id;
            this.semaphore = semaphore;
        }

        public void run() {
            try {
                semaphore.acquire();
                System.out.printf("Worker %d acquired the semaphore, start to work\n", id);

                Thread.sleep(2000);  // 模拟完成某些操作

                semaphore.release();
                System.out.printf("Worker %d released the semaphore\n", id);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

运行结果如下:

Worker 0 acquired the semaphore, start to work
Worker 1 acquired the semaphore, start to work
Worker 2 acquired the semaphore, start to work
Worker 3 is blocked by the semaphore
Worker 4 is blocked by the semaphore
Worker 7 is blocked by the semaphore
Worker 6 is blocked by the semaphore
Worker 5 is blocked by the semaphore
Worker 9 is blocked by the semaphore
Worker 8 is blocked by the semaphore
Worker 0 released the semaphore
Worker 2 released the semaphore
Worker 1 released the semaphore
Worker 7 acquired the semaphore, start to work
Worker 6 acquired the semaphore, start to work
Worker 9 acquired the semaphore, start to work
Worker 8 acquired the semaphore, start to work
Worker 4 acquired the semaphore, start to work
Worker 3 acquired the semaphore, start to work
Worker 5 acquired the semaphore, start to work
Worker 7 released the semaphore
Worker 9 released the semaphore
Worker 8 released the semaphore
Worker 6 released the semaphore
Worker 5 released the semaphore
Worker 4 released the semaphore
Worker 3 released the semaphore

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C++实现线程同步的四种方式总结

    C++实现线程同步的四种方式总结 在多线程程序中,线程同步是一个非常重要的问题。为了保证多个线程的正确性和稳定性,我们需要采用线程同步措施,这样才能确保多个线程同时处理共享资源时不会出现数据读写冲突等问题。C++中实现线程同步主要有四种方式:互斥锁、条件变量、信号量和读写锁。 一、互斥锁(Mutex) 1. 互斥锁概念 互斥锁是最基本的线程同步机制。一段代码…

    多线程 2023年5月16日
    00
  • Java多线程中断机制三种方法及示例

    先给大家介绍一下这篇攻略的目录: 目录 Java多线程中断机制简介 interrupt()方法 示例1:线程在睡眠时被中断 示例2:线程使用while循环时被中断 isInterrupted()方法 示例3:判断是否被中断 interrupted()方法 示例4:判断是否被中断并清除中断标志位 现在我们来一步步讲解每个部分的内容。 Java多线程中断机制简介…

    多线程 2023年5月17日
    00
  • C++ 多线程之互斥量(mutex)详解

    C++ 多线程之互斥量(mutex)详解 什么是互斥量? 在C++中,当多个线程同时访问共享资源时,可能会发生数据冲突或数据竞争的问题,导致程序出错。互斥量就是一种保持互斥、防止数据冲突的机制。在使用互斥量时,只有获取了互斥量的线程才能访问被保护的共享资源,其他线程必须等待。当获取互斥量的线程访问结束并释放互斥量后,其他线程才能继续获取互斥量并访问共享资源。…

    多线程 2023年5月17日
    00
  • Python多线程threading和multiprocessing模块实例解析

    Python 多线程和多进程模块实例解析 概述 Python 是一种解释型语言,它天然支持多线程和多进程。 在 Python 中,多线程和多进程是通过 threading 和 multiprocessing 两个模块来实现的。这两种技术可以帮助我们实现并发编程,提高代码的执行效率。 Python threading 模块 threading 模块提供了一种在…

    多线程 2023年5月17日
    00
  • Java多线程深入理解

    Java多线程深入理解攻略 在进行深入理解Java多线程的过程中,需要掌握以下几点: 1. 线程的创建和启动 Java中线程的创建有两种方式,一种是继承Thread类,一种是实现Runnable接口。其中,实现Runnable接口的方式更加灵活,因为一个类可以实现多个接口。 // 继承Thread类 class MyThread extends Thread…

    多线程 2023年5月16日
    00
  • Java系统的高并发解决方法详解

    下面是Java系统的高并发解决方法详解的完整攻略。 1. 引言 当前,Java 是一种流行的编程语言,并且在企业级软件和 Web 应用程序开发中被广泛使用。然而,高并发是现代互联网应用程序中面临的一个重要挑战,因此如何应对高并发已成为开发人员必须面对的重要问题。本文中,我们将探讨 Java 系统的高并发解决方法。 2. 高并发的影响因素 在开始介绍 Java…

    多线程 2023年5月16日
    00
  • Go并发同步Mutex典型易错使用场景

    Go并发同步中的Mutex是一种锁机制,用于保护共享资源,防止并发访问时出现数据竞争等问题。然而,Mutex被错误地使用会导致诸多问题,因此我们需要了解Mutex的典型易错使用场景。 Mutex使用场景 Mutex的主要使用场景是多个线程同时访问共享资源时,在访问时需要对资源进行加锁、解锁操作,以避免竞争情况下数据的不一致。以下是Mutex的典型使用场景: …

    多线程 2023年5月17日
    00
  • spring-boot 多线程并发定时任务的解决方案

    让我来为您详细讲解如何使用Spring Boot来实现多线程并发定时任务的解决方案。 1. 前言 Spring Boot是目前最流行的Java Web框架之一,而定时任务是后端应用中经常遇到的需求,如何在Spring Boot中高效地实现多线程并发定时任务呢? 传统的Java定时任务一般使用Timer或者ScheduledExecutorService来完成…

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部