【问题标题】:CountDownLatch example in Java Concurrency In PracticeJava并发实践中的CountDownLatch示例
【发布时间】:2014-04-12 02:59:39
【问题描述】:

我正在阅读 Java Concurrency In Practice 一书并遇到了 CountDownLatch。

下面是给出的例子:

public class TestHarness {
    public long timeTasks(int nThreads, final Runnable task)
        throws InterruptedException {

        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(nThreads);

        for (int i = 0; i < nThreads; i++) {
            Thread t = new Thread() {

                public void run() {
                    try {
                        startGate.await();
                        try {
                            task.run();
                        } finally {
                            endGate.countDown();
                        }
                    } catch (InterruptedException ignored) { }
                }
            };
            t.start();
        }
        long start = System.nanoTime();
        startGate.countDown();
        endGate.await();
        long end = System.nanoTime();
        return end-start;
    }
}

这是它的解释:

清单 5.11 中的TestHarness 说明了闩锁的两种常见用途。 TestHarness 创建多个运行给定任务的线程 同时。它使用两个闩锁,一个“起始门”和一个“结束门” 门”。起始门初始化为计数为 1; 结束门被初始化为计数等于工人的数量 线程。每个工作线程做的第一件事就是等待 起跑门;这确保了它们都不会开始工作,直到 他们都准备好开始了。每个人做的最后一件事就是倒计时 在终点门上;这允许主线程有效地等待 直到最后一个工作线程完成,所以它可以 计算经过的时间。

我是 Java 多线程的新手,所以我无法理解给出的解释以及该程序的工作原理。

这是什么意思-

每个工作线程做的第一件事就是等待起始门; 这可以确保在他们都准备好之前,他们都不会开始工作 开始。每个人做的最后一件事就是倒计时结束门。 这允许主线程有效地等待,直到最后一个 工作线程已经完成,所以它可以计算经过的时间。

以及这段代码是如何工作的:

Thread t = new Thread() {

    public void run() {
        try {
            startGate.await();
            try {
                task.run();
            } finally {
                endGate.countDown();
            }
        } catch (InterruptedException ignored) { }
    }
};

long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end-start;

请帮助我理解这个概念。

【问题讨论】:

  • 如果你不知道多线程是如何工作的,为什么要从CountDownLatch开始呢?慢下来。开始here
  • @SotiriosDelimanolis,我正在使用这本书学习多线程概念,因为这是许多 SO 专家的建议。但是我很难理解这个例子。
  • 本书不应该用作多线程的介绍,您可以在如何使用本书部分清楚地阅读。然后,同一部分列出了建议的介绍性资源。
  • 启动线程需要时间。因此,如果每个线程在启动后立即执行其任务,则一些线程可能已经在运行,而另一些则尚未创建。所以他们使用闩锁等待,直到主线程发出启动信号。就像在真正的跑步比赛中一样。当他们完成他们的任务时,他们会发出信号,这样主线程就可以知道他们什么时候都完成了。
  • 图片赛马比赛直到所有马都在起跑线上才开始,直到最后一匹到达终点线才结束。

标签: java multithreading concurrency


【解决方案1】:

这段代码

Thread t = new Thread() {

    public void run() {
        try {
            startGate.await();
            try {
                task.run();
            } finally {
                endGate.countDown();
            }
        } catch (InterruptedException ignored) { }
    }
};

设置所有需要的线程。每个线程将等待startGate 被“打开”,即。它的计数变为0。当线程完成执行Runnable,即。 run() 返回,他们会倒计时endGate。就是这个

每个工作线程做的第一件事就是等待起始门; 这可以确保在他们都准备好之前,他们都不会开始工作 开始。每个人做的最后一件事就是倒计时结束门;

意思。

当所有线程都设置好后,就会执行这段代码。

long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end-start;

当前线程倒计时startGate,这允许所有其他线程开始执行它们的Runnable,即。 task.run()。然后它在endGate 上等待(块)倒计时到 0。此时,它计算花费了多长时间并返回该值。就是这个

这允许主线程有效地等待,直到最后一个 工作线程已经完成,所以它可以计算经过的时间。

意思

【讨论】:

    【解决方案2】:

    确实不是很清楚你的实际问题是什么,或者只要不清楚你已经知道什么,应该如何解释代码。

    但是,这里使用的概念并没有那么复杂,通过删除错误处理并使用内联 cmets 指出重要部分,它可能已经变得更加清晰:

    for (int i = 0; i < nThreads; i++) {
    
        // This will create and start a new thread
        // that executes the code in the "run" method
        Thread t = new Thread() {
            public void run() {
    
                // Wait until this thread gets the start signal
                startGate.await();
    
                // Perform some arbitrary work
                task.run();
    
                // Notify everybody that this thread has finished his work
                endGate.countDown();
            }
        };
        t.start(); 
    }
    
    // Give all threads the start signal: Counting down
    // where will cause the latch to reach the value 0,
    // and every thread that is waiting at "startGate.await()"
    // will proceed his work
    startGate.countDown();
    
    // Wait here until all threads have called "endGate.countDown()".
    endGate.await();
    

    【讨论】:

      【解决方案3】:

      startGate 最初设置为 1,因此所有线程都会等待,直到它倒计时。

      endGate 被初始化为我们计划使用的线程数,因此它将等到所有线程都通过结束门后才报告所用时间。

      // Take a note of the time.
      long start = System.nanoTime();
      // Start all of the threads running - they all wait for this signal by calling startGate.await().
      startGate.countDown();
      // Wait for all threads to complete - they record their finish with endGate.countDown().
      endGate.await();
      // Note the time.
      long end = System.nanoTime();
      

      【讨论】:

        【解决方案4】:
        package com.sample.thread;
        
        import java.util.concurrent.CountDownLatch;
        
        public class CDLExample {
        
        private static CountDownLatch latch;
        
        public static void main(String args[]) {
            latch = new CountDownLatch(2);
        
            new Thread("main") {
                public void run() {
                    try {
                        latch.await();
                        System.out
                                .println("\nStarting Main thread as all other thread is started");
                        System.out.println("CountDownLatch demonstrated: "
                                + Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        
            }.start();
        
            new Thread("first") {
                public void run() {
                    System.out.println("Print Odd Number: "
                            + Thread.currentThread().getName());
                    try {
                        for (int i = 1; i < 20; i = i + 2) {
                            System.out.print(i + " ");
                            Thread.sleep(50);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    latch.countDown();
                }
            }.start();
        
            new Thread("second") {
                public void run() {
                    try {
                        Thread.sleep(1000);
                        System.out.println("\nPrint Even Number: "
                                + Thread.currentThread().getName());
        
                        for (int i = 2; i < 20; i = i + 2) {
                            Thread.sleep(50);
                            System.out.print(i + " ");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    latch.countDown();
                }
            }.start();
        }
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-08
          • 2018-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-01
          • 1970-01-01
          相关资源
          最近更新 更多