日志记录、埋点是较为常见的生产者-消费者模式使用场景,应用的主线程以及其他业务子线程作为生产者,在需要的时候向共享队列中插入日志或者埋点数据,消费者子线程则会从队列中将日志或者埋点信息取出,并进行相关业务处理,比如落盘、上云等。这样所有的日志、埋点处理均在子线程中完成,不占用主线程执行时间。并且业务独立,可以通过独立的团队进行开发,其他业务团队只需要向队列中插入数据即可。
生产者-消费者模式简介
生产者-消费者模式是一种经典的多线程设计模式,它为多线程间的协同提供了良好的解决方案。
在生产者-消费者模式中,通常有两类线程,即若干个生产者线程和若干个消费者线程。生产者线程负责提交用户请求,消费线程负责具体处理生产者提交的任务。生产者和消费者直接则通过共享内存缓冲区进行通信。
从图中可以得看出生产者-消费者模式的如下优点
-
性能提升:将一个耗时的流程拆成生产和消费两个阶段。
-
业务解耦:共享内存缓冲区作为生产者线程和消费者线程间的通信桥梁,避免了生产者线程与消费者线程直接通信,从而将两类线程进行解耦。也就是说生产者不需要知道消费者的存在,反之消费者也不需要知道生产者的存在。
-
性能平衡:共享内存缓冲区的设计也可以很好的解决生产者与消费者线程间的性能上的差异,可以通过调整慢的一方的并发数,从而提高任务的整体处理速度。
生产者-消费者模式的实现
在ArkTS上由于没有java的wait/notify机制(线程挂起并释放锁,线程唤醒),因此在ArkTS上只能通过同步队列的方式实现生产者-消费者模式。
同步队列方案中,我们需要构建一个队列来作为共享缓冲区,生产者线程通过执行offer操作,向缓冲区中添加数据;消费者线程从通过poll操作从缓冲区取出数据。
在实现生产者-消费者模式之前,我们需要先完成内存缓存区的开发。
共享内存缓冲区的实现
共享内存缓冲需要被多个线程使用(offer、poll),因此需要使用Sendable实现、。在生产者-消费者模式中,缓冲区采用FIFO的方式进行队列管理,又由于多个线程都需要对队列进行操作,因此对于队列的操作必须是线程安全的。
基于以上思想,我们需要先实现节点对象`ShareNode`,由于需要在多个线程间共享,所以他必须是Sendble类型变量。其中`item`表示节点的指,`next`为指向下一个节点的指针。
@