`
sharong
  • 浏览: 492588 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
D1667ae2-8cfc-3b68-ac7c-5e282789fa4a
论开源
浏览量:8695
7eb53364-fe48-371c-9623-887640be0185
Spring-data-j...
浏览量:13029
社区版块
存档分类
最新评论

闭锁CountDownLatch和栅栏CyclicBarrier之异同举例

阅读更多
CountDownLatch和CyclicBarrier的主要联系和区别如下:
1.闭锁CountDownLatch做减计数,而栅栏CyclicBarrier则是加计数。
2.CountDownLatch是一次性的,CyclicBarrier可以重用。
3.CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等,等大家都完成。
4.鉴于上面的描述,CyclicBarrier在一些场景中可以替代CountDownLatch实现类似的功能。

另外,值得一提的是,CountDownLatch和CyclicBarrier在创建和启动线程时,都没有明确提到同时启动全部线程,事实上这在技术上是不大可能,不必要,不提倡的。

先看例子一:
class SubRunnable implements Runnable {
	private CountDownLatch begin, end;
	private List<Integer> sublist;
	
	public SubRunnable(List<Integer> sublist, CountDownLatch begin,CountDownLatch end) {
		this.sublist = sublist;
		
		this.begin = begin;
		this.end = end;
	}
	
	@Override
	public void run() {
		try {
			begin.await();			
			
			if (sublist != null) {
				for (int i : sublist) {
					System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally{
			System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");
			end.countDown();
		}
	}
}

public class BatchWithCountDownLatch {
	private static final int MAX = 3;
	
	private static void list(List<Integer> list) {
		if(list == null){
			list = new ArrayList<Integer>();
		}
		
		for(int i = 0 ;i < 1000;i++){
			list.add(i);
		}
	}

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list(list);
		
		//把list拆分成多个
		int mod = list.size() % MAX;
		int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;
		ExecutorService executors = Executors.newFixedThreadPool(threadCount);
		
		CountDownLatch begin = new CountDownLatch(1); 
		CountDownLatch end = new CountDownLatch(threadCount); 
				
		for(int i = 0; i< threadCount;i++){
			int subsize = (i + 1) * MAX;
			executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),begin,end));
		}
		
		System.out.println("开始 !");
		begin.countDown();
		long startTime = System.currentTimeMillis();
		
		try {
			end.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");
			System.out.println("花费时间 -> " + (System.currentTimeMillis() - startTime) + " ms");
		}
		
		System.out.println("开始进入第二步操作! ");		
		
		System.out.println("end! ");
	}
}

这是根据jdk文档中的伪代码例程,编写的一个例子,我们完全可以将这个例程改为只使用一个CountDownLatch来实现之。经过测试,发现begin的引入对程序基本无用,当list是1000的数量级时,最先启动的线程仍然比最后启动的快几十毫秒左右;而不设置begin开始闭锁的程序,也是完全一样的情况。

例子二:
class SubRunnable implements Runnable {
	private CyclicBarrier cyclicBarrier;
	private List<Integer> sublist;
	
	public SubRunnable(List<Integer> sublist, CyclicBarrier cyclicBarrier) {
		this.sublist = sublist;
		this.cyclicBarrier = cyclicBarrier;
	}
	
	@Override
	public void run() {		
		try {
			System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");
			if(sublist != null){
				for(int i : sublist){
					System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);
				}
			}

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

public class ReplaceCountDownLatch {
	private static final int MAX = 3;
	
	private static void list(List<Integer> list) {
		if(list == null){
			list = new ArrayList<Integer>();
		}
		
		for(int i = 0 ;i < 10;i++){
			list.add(i);
		}
	}
	
	public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
		List<Integer> list = new ArrayList<Integer>();
		list(list);

		//把list拆分成多个
		int mod = list.size() % MAX;
		int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;
		ExecutorService executors = Executors.newFixedThreadPool(threadCount);

		final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount,new Runnable() {
			@Override
			public void run() {
				//根据jdkdoc里的描述,哪个线程最后运行完,就执行下面的代码。
				System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");
			}
		});
		
		for(int i = 0; i< threadCount;i++){
			int subsize = (i + 1) * MAX;
			executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),cyclicBarrier));
		}
		
		cyclicBarrier.await();
		executors.shutdown();
		System.out.println("开始进入第二步操作! ");
		
		
		System.out.println("end! ");
	}
}

使用栅栏CyclicBarrier实现和上面闭锁CountDownLatch相同的功能。
0
0
分享到:
评论

相关推荐

    CountDownLatch和CyclicBarrier用法实例大全

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...

    Java中的CountDownLatch与CyclicBarrier:深入理解与应用实践

    在Java的并发编程中,CountDownLatch和CyclicBarrier是两个非常重要的同步工具,它们用于协调多个线程的执行顺序。本文将详细介绍CountDownLatch和CyclicBarrier的工作原理、使用场景以及如何在实际项目中应用它们。...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...

    CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

    ### CountDownLatch 和 CyclicBarrier 的运用(含AQS详解) #### CountDownLatch **定义与特点:** CountDownLatch 是 Java 并发包中的一个重要组件,它主要用于解决“一个或多个线程等待其他线程完成任务”的问题。...

    详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    在Java并发编程中,CountDownLatch和CyclicBarrier都是用于协调多线程间同步的重要工具,它们可以帮助开发者在特定条件满足时启动或者结束线程的执行。本文将详细探讨这两个类的内部实现机制以及它们在实际应用场景...

    java并发工具包详解

    12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService ...

    CountDownLatch、CyclicBarrier、Semaphore.md

    java 高并发应用场景

    Java并发编程之栅栏(CyclicBarrier)实例介绍

    与闭锁(CountDownLatch)不同,闭锁通常是一次性的,而CyclicBarrier可以重用,即“循环”在每次所有线程都到达屏障点后重新初始化。 1. **CyclicBarrier的基本概念**: - **屏障点**:CyclicBarrier的核心是屏障...

    java并发工具包 java.util.concurrent中文版用户指南pdf

    12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService ...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf

    闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService 19....

    mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁)

    本文将详细介绍如何利用MyBatis结合多线程和CountDownLatch闭锁来实现数据的批量插入。 首先,我们来看`mybatis批处理`。MyBatis的批处理功能允许我们在一次数据库连接中执行多条SQL语句,从而减少了数据库连接的...

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

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 Java并发编程是Java语言中的一种高级技术,用于处理多线程编程中的同步问题。Java 1.5中引入了几个高效的辅助类,包括CountDownLatch、...

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是三种重要的线程协作工具,它们都基于AbstractQueuedSynchronizer(AQS)框架来实现线程间的同步和协调。AQS是一个内置的锁和同步组件,它为构建高级...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版

    12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService ...

    详解java多线程的同步控制

    目录线程安全 Thread Safety重入锁 ReentrantLock读写锁 ReadWriteLock倒计数器 CountDownLatch循环栅栏 CyclicBarrier信号量 Semaphore 线程安全 Thread Safety JMM JMM(Java Memory Model)是一种基于计算机内存...

    J.U.C-AQS框架同步组件之闭锁CountDownLatch介绍

    CountDownLatch的设计基于AbstractQueuedSynchronizer(AQS),这是一个用于构建锁和同步组件的基础框架。 CountDownLatch的构造函数接收一个整数参数`count`,这个参数代表了计数器的初始值。当并发执行的线程调用...

    java并发包资源

    12. 闭锁 CountDownLatch 13. 栅栏 CyclicBarrier 14. 交换机 Exchanger 15. 信号量 Semaphore 16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService ...

    Java并发编程之闭锁与栅栏的实现

    在Java并发编程中,闭锁和栅栏是两种重要的同步工具,它们可以帮助开发者在多线程环境下控制线程的执行顺序和同步。本篇文章将详细解释这两种机制,并通过实例代码进行演示。 一、闭锁(CountDownLatch) 闭锁,由...

Global site tag (gtag.js) - Google Analytics