CountDownLatch类使我们能够通过引入对正在执行相关任务的线程数量的感知并跟踪已经完成其任务的线程数量来协调线程。
这是通过用工作线程的数量初始化CountDownLatch来完成的。每个工作线程都应该调用 countDown() CountDownLatch上的方法。需要等待工作线程完成的线程应该调用 await() CountDownLatch上的方法。这将导致该线程一直等待,直到所有工作线程都调用了 countDown() 方法,实际上是从工作线程数递减到零。一旦倒计时到达零,调用 await() 可以继续。
下面的示例说明了如何在两种不同的情况下使用CountDownLatch。
在这个例子中,让我们考虑一个场景,其中许多比萨饼制造商制作一些比萨饼。由不同的比萨饼制造商制作的比萨饼然后被收集起来交付给饥饿的顾客。
为了实现这一点,我们使用一个线程来代表每一个比萨饼制造商。这些东西越多,同时做的披萨就越多。下面是 PizzaMaker 班级。
请注意,构造函数接受一个 CountDownLatch 。这将由等待完成的调用线程传入。每个 PizzaMaker 实例将需要调用 countDown() 方法来指示其工作的完成。如上面的代码所示,这是在 make() 方法一旦所有的比萨饼都做好了。
下面的代码演示了如何使用 CountDownLatch 以及如何阻塞主线程,直到所有的比萨饼制造商都制作好了比萨饼。
该代码创建了四个pizza makers,并将相同的CountDownLatch传递给它们中的每一个。注意,CountDownLatch是用比萨饼制造商的数量实例化的。每一个负责制作三个比萨的比萨制作师都在一个单独的线程中运行。
然后主线程调用 await() 在……上 CountDownLatch ,因此要等到所有四个比萨饼制造商都调用了 countDown() 。一旦发生这种情况,主线程就开始将来自所有四个比萨饼制造商的比萨饼收集到一个集合中。
代码的输出如下所示:
我们可以看到最后的信息 12 pizzas ready to go! 在所有的比萨饼都由四个不同的比萨饼师傅做好之后显示。这就是如何使用CountDownLatch来阻塞一个线程,直到多个线程完成它们的任务。
在这个例子中,我们将拉伸pizza面团——对不起,场景——来说明如何使用CountDownLatch让线程池等待,直到满足某个条件。
在这个例子中,让我们考虑这样一个场景,许多比萨饼制作者正在等待他们的配料被取出,以便他们可以开始制作比萨饼。
为了实现这一点,每个比萨饼制作机将在一个单独的线程中运行,就像前面的例子一样。但是,这些线程需要等到满足条件(配料交付)后才能开始执行任务。
我们修改了 PizzaMaker 类来接收一个附加的 CountDownLatch 比萨饼制作者在制作比萨饼之前必须等待
然后,我们修改 make() 方法来调用 await() 在……上 ingredientsCountDownLatch 因此每个比萨饼制作者在尝试制作比萨饼之前都要等待配料被取出:
下面的演示代码显示了这种情况下的协调是如何完成的:
请注意新的CountDownLatch — ingredientsCountDownLatch —初始化为计数1,因为只有主线程将获取配料。一旦 fetchIngredients() 方法完成后,主线程调用 countDown() 在 ingredientsCountDownLatch ,这导致每个 PizzaMaker 线程停止等待,并继续使比萨饼。
和以前一样,主线程调用 await() 在……上 CountDownLatch 与比萨饼制造商相关联,导致它一直等到所有比萨饼都准备好。
输出现在看起来像这样:
我们可以看到,这四个比萨饼制造商在继续制作比萨饼之前,正在等待取来配料。最后的信息 12 pizzas ready to go! 在所有披萨都准备好之后显示。因此,我们在主线程和 PizzaMaker 线程。
值得注意的是,有一个变种的 await() 方法,该方法采用超时参数,以便调用线程可以避免无限期等待。
我们已经看到了一个简单而有用的例子,展示了如何使用CountDownLatch以灵活的方式协调并发任务。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)