字节面试题: Kotlin 中处理生产者/消费者问题的 N 种方式?

本文探讨了Kotlin中解决生产者/消费者问题的多种方法,包括Synchronized、ReentrantLock、BlockingQueue、Semaphore、PipedXXXStream、RxJava、Coroutine Channel和Flow。重点介绍了它们的适用场景和优缺点,强调了阻塞队列和协程在处理这类问题上的优势。
摘要由CSDN通过智能技术生成

生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个缓冲区(Buffer),生产者往 Buffer 中添加产品,消费者从 Buffer 中取走产品,当 Buffer 为空时,消费者阻塞,当 Buffer 满时,生产者阻塞。

Kotlin 中有多种方法可以实现多线程的生产/消费模型(大多也适用于Java)

  • Synchronized
  • ReentrantLock
  • BlockingQueue
  • Semaphore
  • PipedXXXStream
  • RxJava
  • Coroutine
  • Flow

1. Synchronized

ynchronized 是最最基本的线程同步工具,配合wait/notify可以实现实现生产消费问题

val buffer = LinkedList<Data>()
val MAX = 5 //buffer最大size

val lock = Object()

fun produce(data: Data) {
    sleep(2000) // mock produce
    synchronized(lock) {
        while (buffer.size >= MAX) {
           // 当buffer满时,停止生产
           // 注意此处使用while不能使用if,因为有可能是被另一个生产线程而非消费线程唤醒,所以要再次检查buffer状态
           // 如果生产消费两把锁,则不必担心此问题
           lock.wait()
        }

		    buffer.push(data)
        // notify方法只唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。
        // notifyAll会唤醒所有等待中线程,哪一个线程将会第一个处理取决于操作系统的实现,但是都有机会处理。
        // 此处使用notify有可能唤醒的是另一个生产线程从而造成死锁,所以必须使用notifyAll
        lock.notifyAll()
    }
}

fun consume() {
    synchronized(lock) {
        while (buffer.isEmpty())
            lock.wait() // 暂停消费
        buffer.removeFirst()
        lock.notifyAll()
    }
    sleep(2000) // mock consume
}



@Test
fun test() {
    // 同时启动多个生产、消费线程
    repeat(10) {
        Thread { produce(Data()) }.start()
    }
    repeat(10) {
        Thread { consume() }.start()
    }
}

2. ReentrantLock

Lock 相对于 Synchronized 好处是当有多个生产线/消费线程时,我们可以通过定义多个condition精确指定唤醒哪一个。下面的例子展示 Lock 配合await/single替换前面 Synchronized 写法

val buffer = LinkedList<Data>()
val MAX = 5 //buffer最大size
             
val lock = ReentrantLock()                     
val condition = lock.newCondition()          
                                               
fun produce(data: Data) {                      
    sleep(2000) // mock produce                
    lock.lock()                                
                                               
    while (buffer.size >= 5)  
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值