java生产者消费者 怎么处理均衡

Python017

java生产者消费者 怎么处理均衡,第1张

用多个线程,既有消费者的,也有生产者的,通过一个共同的队列放入和取出产品,然后写好控制语句就可以了。如果对他们运行的均衡很苛刻的话,还得写一个监控的线程,在什么条件下发生了不均衡立马报警,然后采取相应的措施,该迅速加大生产,还是该开仓放粮。

有可能的话,用上栅栏(cyclicbarrier)或者是闭锁(countdownlatch)就好了。

注意一点的是一定要将锁用好,否则会发生死锁或者意向不到的问题。

从Java 5开始,核心的Java APIs得到了增强,增加了更多处理并发编程中线程间协调的特性。在本文中,我们将讨论java.util.concurrent包中有助于实现这一目的的一个类闭锁.

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以灵活的方式协调并发任务。

Redisson的分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口,同时还支持自动过期解锁。

Redisson同时还为分布式锁提供了异步执行的相关方法:

Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。在提供了自动过期解锁功能的同时,保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。

Redisson同时还为分布式可重入公平锁提供了异步执行的相关方法:

Redisson的RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。

Redisson的RedissonRedLock对象实现了 Redlock 介绍的加锁算法。该对象也可以用来将多个RLock

对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。

Redisson的分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。同时还支持自动过期解锁。该对象允许同时有多个读取锁,但是最多只能有一个写入锁。

Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。

Redisson的可过期性信号量(PermitExpirableSemaphore)实在RSemaphore对象的基础上,为每个信号增加了一个过期时间。每个信号可以通过独立的ID来辨识,释放时只能通过提交这个ID才能释放。

Redisson的分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。

Redisson 分布式锁和同步器