【孔乙已】生产者消费者有四样写法,你知道吗?

Lock中的Condition可以实现上面Objectwait,notify一样的效果
await对应wait,signal对应notify,signalAll对应notifyAll
下面直接来看看实现,代码与使用wait,notify基本上是一样的,只是同步方式不同

public class ProductorConsumerDemo2 {

private static ReentrantLock lock = new ReentrantLock();
private static Condition full = lock.newCondition();
private static Condition empty = lock.newCondition();

public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 5; i++) {
service.submit(new Productor(linkedList, 8, lock));
}
for (int i = 0; i < 10; i++) {
service.submit(new Consumer(linkedList, lock));
}

}

static class Productor implements Runnable {

private List list;
private int maxLength;
private Lock lock;

public Productor(List list, int maxLength, Lock lock) {
this.list = list;
this.maxLength = maxLength;
this.lock = lock;
}

@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.size() == maxLength) {
System.out.println(“生产者” + Thread.currentThread().getName() + " list以达到最大容量,进行wait");
full.await();
System.out.println(“生产者” + Thread.currentThread().getName() + " 退出wait");
}
Random random = new Random();
int i = random.nextInt();
System.out.println(“生产者” + Thread.currentThread().getName() + " 生产数据" + i);
list.add(i);
empty.signalAll();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}

static class Consumer implements Runnable {

private List list;
private Lock lock;

public Consumer(List list, Lock lock) {
this.list = list;
this.lock = lock;
}

@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.isEmpty()) {
System.out.println(“消费者” + Thread.currentThread().getName() + " list为空,进行wait");
empty.await();
System.out.println(“消费者” + Thread.currentThread().getName() + " 退出wait");
}
Integer element = list.remove(0);
System.out.println(“消费者” + Thread.currentThread().getName() + " 消费数据:" + element);
full.signalAll();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}

}

3.BlockingQueue方式实现

由于BlockingQueue内部实现就附加了两个阻塞操作。
即当队列已满时,阻塞向队列中插入数据的线程,直至队列中未满;当队列为空时,阻塞从队列中获取数据的线程,直至队列非空时为止.
所以使用BlockingQueue来实现生产者消费者模式非常简单方便,关于BlockingQueue的更多细节可见:并发容器之BlockingQueue详解

下面直接看下生产者消费者实现

public class ProductorConsumerDmoe3 {

private static LinkedBlockingQueue queue = new LinkedBlockingQueue<>();

public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 5; i++) {
service.submit(new Productor(queue));
}
for (int i = 0; i < 10; i++) {
service.submit(new Consumer(queue));
}
}

static class Productor implements Runnable {
private BlockingQueue queue;

public Productor(BlockingQueue queue) {
this.queue = queue;
}

@Override
public void run() {
try {
while (true) {
Random random = new Random();
int i = random.nextInt();
System.out.println(“生产者” + Thread.currentThread().getName() + “生产数据” + i);
queue.put(i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

static class Consumer implements Runnable {
private BlockingQueue queue;

public Consumer(BlockingQueue queue) {
this.queue = queue;
}

@Override
public void run() {
try {
while (true) {
Integer element = (Integer) queue.take();
System.out.println(“消费者” + Thread.currentThread().getName() + “正在消费数据” + element);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

4.Kotlin Channel方式实现

随着Kotlin的普及,使用协程来处理并发也变成了一个更加方便的选择
使用Kotlin Channel同样可以实现生产者消费者模式

1.一个 Channel 是一个和 BlockingQueue 非常相似的概念。
2.Channel相比BlockingQueue代替了阻塞的 put 操作并提供了挂起的 send,还替代了阻塞的 take 操作并提供了挂起的 receive
3.相比BlockingQueue的阻塞,Channel的挂起性能更好
4.Channel还有个特点是阻塞队列没有,它可以随时关闭,当发送者接收到关闭指令,将立即停止发送。

实现如下:

fun CoroutineScope.produceSquares(): ReceiveChannel = produce {
for (x in 1…5) {
val item = x * x
println(“生产者生产了:$item”)
send(x * x)
delay(1000)
}
}

fun main() = runBlocking {
val squares = produceSquares()
squares.consumeEach {
println(“消费者消费了$it”)
}
println(“Done!”)
}
通过Channel方式,可以比较方便的实现生产者消费者模式
总结

本文主要介绍了生产者消费者模式的四种写法
1.wait/notify方式实现
2.Lock方式实现
3.BlockingQueue方式实现
4.Kotlin Channel方式实现

参考资料

实现生产者消费者的三种方式
Kotlin Channel与生产者-消费者模式

学习分享,共勉

Android高级架构师进阶之路

题外话,我在阿里工作多年,深知技术改革和创新的方向,Android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人

  • Android进阶知识体系学习脑图

  • Android进阶高级工程师学习全套手册

  • 对标Android阿里P7,年薪50w+学习视频

  • 大厂内部Android高频面试题,以及面试经历

Android进阶高级工程师学习全套手册

[外链图片转存中…(img-otljK5yo-1720110342652)]

  • 对标Android阿里P7,年薪50w+学习视频

[外链图片转存中…(img-hPzu6Pf6-1720110342652)]

  • 大厂内部Android高频面试题,以及面试经历

[外链图片转存中…(img-3KkpF4k7-1720110342653)]

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值