`

CountDownLatch的使用

阅读更多
concurrent包里面的CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值。
CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

      举个例子,有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。所以在这里用Java代码设计两个类,Worker代表工人,Boss代表老板,具体的代码实现如下:

public class Worker implements Runnable{  
      
    private CountDownLatch downLatch;  
    private String name;  
      
    public Worker(CountDownLatch downLatch, String name){  
        this.downLatch = downLatch;  
        this.name = name;  
    }  
     
    public void run() {  
        this.doWork();  
        try
{  
            TimeUnit.SECONDS.sleep(new Random().nextInt(10));  
        }catch(InterruptedException ie){  
        }  
       System.out.println(this.name + "活干完了!");  
        this.downLatch.countDown();  
          
    }  
      
    private void doWork()
    {  
       System.out.println(this.name + "正在干活!");  
    }  
      
}




==================
public class Boss implements Runnable {  
 
    private CountDownLatch downLatch;  
      
    public Boss(CountDownLatch downLatch){  
        this.downLatch = downLatch;  
    }  
      
    public void run() {  
        System.out.println("老板正在等所有的工人干完活......");  
        try {  
            this.downLatch.await();  
        } catch (InterruptedException e) {  
        }  
        System.out.println("工人活都干完了,老板开始检查了!");  
    }  
 
}


============================
 
public class CountDownLatchDemo {  
 
    public static void main(String[] args) {  
       ExecutorService executor = Executors.newCachedThreadPool();  
          
        CountDownLatch latch = new CountDownLatch(3);  
          
        Worker w1 = new Worker(latch,"张三");  
        Worker w2 = new Worker(latch,"李四");  
        Worker w3 = new Worker(latch,"王二");  
          
       Boss boss = new Boss(latch);  
          
        executor.execute(w3);  
        executor.execute(w2);  
        executor.execute(w1);  
        executor.execute(boss);  
          
        executor.shutdown();  
    }  
 
}

分享到:
评论
6 楼 johnawm 2013-01-05  
2012-12-18 
wangshibei 写道
CountDownLatch这个东西还有点用,当计数器减为0时调用的应该是“notifyall”,而不是“notify”,所以只需要“latch”就可以了,不用“doneLatch ”
johnawm 写道
要统计时间你可以再加一个CountDownLatch变量用来表示老板检查结束,如
package methodtest;

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

public class CountDonwLatchTest {
	public static void main(String[] a) {
		long startTime = System.currentTimeMillis();

		ExecutorService executor = Executors.newCachedThreadPool();

		CountDownLatch latch = new CountDownLatch(3);
		CountDownLatch doneLatch = new CountDownLatch(1);
		Worker w1 = new Worker(latch, "张三");
		Worker w2 = new Worker(latch, "李四");
		Worker w3 = new Worker(latch, "王二");

		Boss boss = new Boss(latch, doneLatch);

		executor.execute(w3);
		executor.execute(w2);
		executor.execute(w1);
		executor.execute(boss);

		executor.shutdown();
		try {
			doneLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(System.currentTimeMillis() - startTime);
	}
}

class Worker implements Runnable {
	private CountDownLatch downLatch;
	private String name;

	public Worker(CountDownLatch downLatch, String name) {
		this.downLatch = downLatch;
		this.name = name;
	}

	public void run() {
		this.doWork();
		try {
			TimeUnit.SECONDS.sleep(new Random().nextInt(10));
		} catch (InterruptedException ie) {
		}
		System.out.println(this.name + "活干完了!");
		this.downLatch.countDown();

	}

	private void doWork() {
		System.out.println(this.name + "正在干活!");
	}
}

class Boss implements Runnable {

	private CountDownLatch downLatch;
	private CountDownLatch doneLatch;
	public Boss(CountDownLatch downLatch,CountDownLatch doneLatch) {
		this.downLatch = downLatch;
		this.doneLatch = doneLatch;
	}

	public void run() {
		System.out.println("老板正在等所有的工人干完活...");
		try {
			this.downLatch.await();
		} catch (InterruptedException e) {
		}
		System.out.println("工人活都干完了,老板开始检查了!");
		doneLatch.countDown();
	}

}




有道理!!
5 楼 wangshibei 2012-12-18  
CountDownLatch这个东西还有点用,当计数器减为0时调用的应该是“notifyall”,而不是“notify”,所以只需要“latch”就可以了,不用“doneLatch ”
johnawm 写道
要统计时间你可以再加一个CountDownLatch变量用来表示老板检查结束,如
package methodtest;

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

public class CountDonwLatchTest {
	public static void main(String[] a) {
		long startTime = System.currentTimeMillis();

		ExecutorService executor = Executors.newCachedThreadPool();

		CountDownLatch latch = new CountDownLatch(3);
		CountDownLatch doneLatch = new CountDownLatch(1);
		Worker w1 = new Worker(latch, "张三");
		Worker w2 = new Worker(latch, "李四");
		Worker w3 = new Worker(latch, "王二");

		Boss boss = new Boss(latch, doneLatch);

		executor.execute(w3);
		executor.execute(w2);
		executor.execute(w1);
		executor.execute(boss);

		executor.shutdown();
		try {
			doneLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(System.currentTimeMillis() - startTime);
	}
}

class Worker implements Runnable {
	private CountDownLatch downLatch;
	private String name;

	public Worker(CountDownLatch downLatch, String name) {
		this.downLatch = downLatch;
		this.name = name;
	}

	public void run() {
		this.doWork();
		try {
			TimeUnit.SECONDS.sleep(new Random().nextInt(10));
		} catch (InterruptedException ie) {
		}
		System.out.println(this.name + "活干完了!");
		this.downLatch.countDown();

	}

	private void doWork() {
		System.out.println(this.name + "正在干活!");
	}
}

class Boss implements Runnable {

	private CountDownLatch downLatch;
	private CountDownLatch doneLatch;
	public Boss(CountDownLatch downLatch,CountDownLatch doneLatch) {
		this.downLatch = downLatch;
		this.doneLatch = doneLatch;
	}

	public void run() {
		System.out.println("老板正在等所有的工人干完活...");
		try {
			this.downLatch.await();
		} catch (InterruptedException e) {
		}
		System.out.println("工人活都干完了,老板开始检查了!");
		doneLatch.countDown();
	}

}



4 楼 johnawm 2012-08-28  
要统计时间你可以再加一个CountDownLatch变量用来表示老板检查结束,如
package methodtest;

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

public class CountDonwLatchTest {
	public static void main(String[] a) {
		long startTime = System.currentTimeMillis();

		ExecutorService executor = Executors.newCachedThreadPool();

		CountDownLatch latch = new CountDownLatch(3);
		CountDownLatch doneLatch = new CountDownLatch(1);
		Worker w1 = new Worker(latch, "张三");
		Worker w2 = new Worker(latch, "李四");
		Worker w3 = new Worker(latch, "王二");

		Boss boss = new Boss(latch, doneLatch);

		executor.execute(w3);
		executor.execute(w2);
		executor.execute(w1);
		executor.execute(boss);

		executor.shutdown();
		try {
			doneLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(System.currentTimeMillis() - startTime);
	}
}

class Worker implements Runnable {
	private CountDownLatch downLatch;
	private String name;

	public Worker(CountDownLatch downLatch, String name) {
		this.downLatch = downLatch;
		this.name = name;
	}

	public void run() {
		this.doWork();
		try {
			TimeUnit.SECONDS.sleep(new Random().nextInt(10));
		} catch (InterruptedException ie) {
		}
		System.out.println(this.name + "活干完了!");
		this.downLatch.countDown();

	}

	private void doWork() {
		System.out.println(this.name + "正在干活!");
	}
}

class Boss implements Runnable {

	private CountDownLatch downLatch;
	private CountDownLatch doneLatch;
	public Boss(CountDownLatch downLatch,CountDownLatch doneLatch) {
		this.downLatch = downLatch;
		this.doneLatch = doneLatch;
	}

	public void run() {
		System.out.println("老板正在等所有的工人干完活...");
		try {
			this.downLatch.await();
		} catch (InterruptedException e) {
		}
		System.out.println("工人活都干完了,老板开始检查了!");
		doneLatch.countDown();
	}

}


3 楼 bubiaiyou 2012-08-27  
javac_xinyun 写道
somefuture 写道
如果想统计时间,我这样做
long start871456 = System.currentTimeMillis();

executor.execute(w3);
executor.execute(w2);
executor.execute(w1);
executor.execute(boss);
executor.shutdown();

long end84654856 = System.currentTimeMillis();
System.out.println("运行时间是" + (end84654856 - start871456) + "毫秒");

为什么不行呢?

使用System.nanoTime()试试吧...



System.out.println()是main的线程 不受ExecutorService 管理,他们互补干扰,
2 楼 javac_xinyun 2012-08-09  
somefuture 写道
如果想统计时间,我这样做
long start871456 = System.currentTimeMillis();

executor.execute(w3);
executor.execute(w2);
executor.execute(w1);
executor.execute(boss);
executor.shutdown();

long end84654856 = System.currentTimeMillis();
System.out.println("运行时间是" + (end84654856 - start871456) + "毫秒");

为什么不行呢?

使用System.nanoTime()试试吧...
1 楼 somefuture 2012-08-03  
如果想统计时间,我这样做
long start871456 = System.currentTimeMillis();

executor.execute(w3);
executor.execute(w2);
executor.execute(w1);
executor.execute(boss);
executor.shutdown();

long end84654856 = System.currentTimeMillis();
System.out.println("运行时间是" + (end84654856 - start871456) + "毫秒");

为什么不行呢?

相关推荐

    JAVA多线程CountDownLatch使用详解

    JAVA多线程CountDownLatch使用详解 JAVA多线程CountDownLatch是JAVA多线程编程中的一种同步工具,主要用来让某个线程等待其他线程执行完毕后再继续执行。下面我们将详细介绍JAVA多线程CountDownLatch的使用和原理。...

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

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

    【并发编程】 — CountDownLatch原理简介 + 使用方法

    文章目录1 原理简介2 具体使用方法2.1 demo1 — await不传入时间,保证当前线程的其他操作在最后执行2.2 demo2 — await传入时间t,当前线程等其他线程时间t后就运行其他操作2.3 发令枪 源码地址:...

    CountDownLanch.rar

    CountDownLatch使用实例 - 初始化时,设置计数(count)值,也就是闭锁需要等待的线程数。 - 主线程必须在启动其他线程后立即调用 CountDownLatch.await() 方法,这样主线程的操作就会在这个方法上阻塞,直到其他...

    多线程countDownLatch方法介绍

    本文将深入探讨CountDownLatch的工作原理、使用场景以及相关源码分析。 CountDownLatch是一个计数器,初始化时设定一个初始值,通常表示一个任务的子任务数量。每个线程完成其工作后会调用`countDown()`方法,...

    利用 CountDownLatch 类实现线程同步

    1. **初始化异步操作**:在 Activity 或 Fragment 的生命周期方法中,如果需要先执行一系列异步操作(如网络请求、数据库初始化等)再显示界面,可以使用 `CountDownLatch` 来等待这些异步操作完成。 2. **并发测试...

    framework-analysis:对使用Hibernate出现的问题进行分析;Spring、MyBatis、AQS、ThreadPoolExecutor、CountDownLatch核心源码分析

    于是乎到现在的Hibernate、MyBatis、Spring、Spring MVC、AQS、ThreadPoolExecutor、CountDownLatch使用场景和核心源码分析。 感觉自己还是真的菜鸡,有太多框架的底层实现都不怎么了解。 当山头被一座一座攻克时,...

    CountDownLatch和CyclicBarrier用法实例大全

    4. **一次性使用**: 一旦计数器归0,`await()`将不再阻塞任何线程,且CountDownLatch不能重置,只能一次性使用。 **CyclicBarrier** CyclicBarrier则更像一个障碍,它允许一组线程彼此等待,直到所有的线程都到达...

    CountDownLatch学习用法

    5. **一次性使用**:CountDownLatch的设计是一次性的,即一旦计数器归零,就不能再次使用。如果尝试再次调用`await()`或`countDown()`,它将抛出`IllegalStateException`。 6. **并发性能**:由于CountDownLatch是...

    CountDownLatch练习

    2. **如何避免死锁与饥饿**:在使用CountDownLatch时,要确保所有线程都能正确调用`countDown()`,避免因某个线程异常而无法达到零导致死锁。 3. **如何选择合适的同步工具**:根据场景选择,如果需要所有线程执行完...

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

    4. 线程执行数据插入操作,使用MyBatis的批处理功能提高效率。 5. 线程完成插入后,调用`latch.countDown()`,表示其工作已完成。 6. 主线程在所有线程开始前调用`latch.await()`,等待所有线程完成。 7. 所有线程...

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

    - **CountDownLatch** 是单次使用的,一旦计数器归零,就不能再复用。 - **CyclicBarrier** 可以重用,线程到达屏障点后,屏障会自动重置,允许线程再次等待。 在实际应用中,选择使用哪种工具取决于具体的需求。...

    CountDownLatch同步工具类使用详解

    CountDownLatch同步工具类使用详解 CountDownLatch是一个java.util.concurrent包下的同步工具类,它允许一个或多个线程等待直到在其他线程中一组操作执行完成。CountDownLatch的用法非常简单,它可以用来控制线程的...

    并发编程之CountDownLatch

    CountDownLatch 的主要使用场景包括:实现最大程度的并行性、开始执行前等待 n 个线程完成各自任务、死锁检测等。在实际开发中,CountDownLatch 可以用来实现主线程和子线程之间的通信,例如主线程发送命令启动子...

    如何使用CountDownLatch同步java多线程

    如何使用CountDownLatch同步java多线程 CountDownLatch 是 Java 并发编程中的一种常用工具,用于控制多个线程的并发执行。它可以实现多个线程之间的同步操作,使得线程之间可以协调工作,避免了线程之间的互相干扰...

    CountDownLatch与thread.join()的区别

    CountDownLatch与thread.join()的区别

    CountDownLatch Demo

    - **并发任务分阶段执行**:一个大型任务可以被分解成多个子任务,使用 CountDownLatch 让所有子任务完成后,再执行下一步操作。 5. **注意事项**: - `CountDownLatch` 不是线程安全的,因此计数器一旦递减到零...

    countdownlatch-example-sourcecode.zip

    本文将深入探讨CountDownLatch的工作原理、使用方法以及它在并发编程中的应用场景。 1. **CountDownLatch简介** CountDownLatch是一个计数器,初始化时设置一个初始值,然后多个线程可以等待这个计数器归零。一旦...

    CountDownLatch详解.docx

    CountDownLatch 是 Java 中的一个同步工具类,位于 `java.util.concurrent` 包下,它主要用于多线程间的协作,...正确使用 CountDownLatch 可以提高程序的并发性能,避免不必要的等待,同时确保任务的正确顺序执行。

Global site tag (gtag.js) - Google Analytics