CountDownLatch

本文介绍了Java并发编程中CountDownLatch类的应用场景与实现细节。CountDownLatch能够协调多个线程的启动和停止,使得多个线程可以同时开始运行或者等待所有线程完成任务。文章通过实例演示了如何使用CountDownLatch来同步线程的启动和结束。

http://www.javamex.com/tutorials/threads/CountDownLatch.shtml

 

Coordinating threads with CountDownLatch

 

The CountDownLatch class allows us to coordinate the starting and stopping of threads. Typical uses are as follows:

  • we can make several threads start at the same time ;
  • we can wait for several threads to finish (whereas, for example, the Thread.join() method only lets you wait for a single thread).

Introduction to CountDownLatch

In concurrent programming, a latch is a type of "switch" or "trigger". The latch is set up with a particular count value. The count is then counted down , and at strategic moments, a thread or threads waits for the countdown to reach zero before continuing to perform some process. Note that this is a one-off process : once the latch reaches zero, there is no way to reset the count.

In Java:

  • the CountDownLatch object is constructed with the initial count;
  • calling countDown() decrements the count by 1;
  • the await() method will wait for the count to reach zero, or proceed immediately if the count already reached zero.

The CountDownLatch class is designed to be safe to call from multiple threads without any extra synchronization. (This differs, for example, from the wait/notify mechanism, where threads must be synchronized on the given lock object before calling wait() or notify() .)

Why use CountDownLatch (rather than wait/notify, Condition etc)?

The CountDownLatch protects you against the case of a thread missing a signal which can occur if you use these other mechanisms for coordinating jobs. Something like a Condition is useful for signalling to threads if they are waiting, but where it doesn't matter if they're not, or where a thread will explicitly check if it has to wait before waiting. With a CountDownLatch , we await a signal if it hasn't been triggered yet, but immediately continue without waiting if that signal was already triggered before we start waiting.

How to make several threads start at the same time

Sometimes it is useful to make a group of threads start at approximately the same time. For example, consider performance tests such as the ones conducted for this web site. If we're testing some throughput with n threads, it's only fair if the n threads start (and stop) at more or less the same time. In another situation, we might want a group of threads to start as soon as some asynchronous initialisation procedure is complete.

To coordinate the starting of several threads, we first create a CountDownLatch with an initial count of 1 . Then, each thread will sit at the start of its run() method, waiting for the latch to be counted down (i.e. sitting in the await() method). The thread performing the initialisation step (or just the thread coordinating the start of the other threads in the case of our performance experiment) then calls countDown() on the latch. Because the initial count was 1, this single countdown operation triggers all the other threads to start at (approximately) the same time.

If we define a subclass of Thread to handle the concurrent tasks, then we can arrange to pass the CountDownLatch into the constructor of those threads:

 

public class LatchedThread extends Thread {
  private final CountDownLatch startLatch;

  public LatchedThread(CountDownLatch startLatch) {
    this.startLatch = startLatch;
  }
  public void run() {
    try {
      startLatch.await();
      // ... perform task
    } catch (InterruptedException iex) {}
  }
}

 

Then, to coordinate the starting of 4 of these threads:

 

CountDownLatch startLatch = new CountDownLatch(10);
for (int threadNo = 0; threadNo < 4; threadNo++) {
  Thread t = new LatchedThread(startLatch);
  t.start();
}
// give the threads chance to start up; we could perform
// initialisation code here as well.
Thread.sleep(200);
startLatch.countDown();
 

When we call countDown() in the main thread, we don't actually know that all of the threads have started up; we just assume that sleeping for a fraction of a second gives them a "reasonable chance" of being ready for the signal. If any of the threads "misses the signal", it won't actually matter too much: when such a thread does start up, enter its run() method await() method, it will no longer actually wait, since the latch has already reached zero.

Bear in mind that inevitably, threads will "wake up" with approximate simultaneity : how simultaneous it can actually be depends on various factors, such as whether each thread can actually be allocated to a free processor, how "busy" the system is (what other threads are running and at what priorities), what threads are doing— i.e. how quickly running threads will relinquish the CPU— and what your particular operating system's policy is on prioritising waiting threads when they are signalled to wake up. (See the section on thread scheduling for more details about these factors.)

How to wait for several threads to complete

Another common scenario is with parallel processing , where we need to wait for several threads to finish or reach a particular point. In this case, we can use a similar mechanism:

  • we construct a CountDownLatch with the number of threads we want to wait for;
  • each thread counts down the latch on termination (or on finishing the job we're interested in).

This is therefore more flexible than the join() method, which only lets us wait for a single thread. Here is an example of waiting for 10 threads to complete:

 

public class StopLatchedThread extends Thread {
  private final CountDownLatch stopLatch;
  
  public StopLatchedThread(CountDownLatch stopLatch) {
    this.stopLatch = stopLatch;
  }
  public void run() {
    try {
      // perform interesting task
    } finally {
      stopLatch.countDown();
    }
  }
}

public void performParallelTask() throws InterruptedException {
  CountDownLatch cdl = new CountDownLatch(10);
  for (int i = 0; i < 10; i++) {
    Thread t = new StopLatchedThread(cdl);
    t.start();
  }
  cdl.await();
}
 

Interruptions and timeouts

A thread sitting in the await() method can be interrupted (generally by another thread calling interrupt() on it). Therefore, the await() method throws InterruptedException . Inside a run() method, the most appropriate action is usually to catch the exception around the whole logic of the method, so that interrupting the thread makes it exit. Where we are waiting for threads to complete inside a method, we can just make that method throw the exception up, and let the caller worry about what happens if the process is interrupted. For more information, see the section on thread interruption .

A version of the await() method takes a timeout (and TimeUnit in which the timeout is specified). Setting a timeout could be useful if, for example, the condition that a thread is awaiting is the initialisation of a driver, and there's a chance that the driver will not get initialised in a reasonably amount of time. In the timed case, the method returns true if the latch was actually triggered, and false if a timeout occurred. The timed method can still be interrupted and throw InterruptedException .

Coordinating multi-stage/iterated parallel processes

The CountDownLatch is useful for coordination of one-off operations. In the next section, we look at the CyclicBarrier class, which allows repeated or multi-stage parallel processes to be coordinated.

 

 

 

 

 

 

 

提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习和研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度和稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能和输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习和修改: 通过阅读模型中的注释和查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)内容概要:本文研究了一种基于遗传算法的新型异构分布式系统任务调度算法,并提供了Matlab代码实现。文章重点围绕异构环境中任务调度的优化问题,利用遗传算法进行求解,旨在提高资源利用率、降低任务完成时间并优化系统整体性能。文中详细阐述了算法的设计思路、编码方式、适应度函数构建、遗传操作流程及参数设置,并通过仿真实验验证了该算法相较于传统方法在调度效率和收敛性方面的优越性。此外,文档还列举了大量相关领域的研究案例和技术应用,涵盖电力系统、路径规划、车间调度、信号处理等多个方向,体现出较强的技术综合性与实践价值。; 适合人群:具备一定编程基础和优化算法知识的研究生、科研人员及从事智能优化、分布式系统调度、电力系统、自动化等相关领域的工程技术人员。; 使用场景及目标:①解决异构分布式系统中的任务调度优化问题;②学习遗传算法在实际工程问题中的建模与实现方法;③为科研项目提供算法参考与代码复现支持;④拓展多领域交叉应用的研究思路。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注适应度函数设计与遗传操作流程,并尝试在不同场景下调整参数以观察性能变化。同时可参考文中列出的相关研究方向进行延伸探索,提升综合应用能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值