在功能设计上,我崇尚奥卡姆剃刀法则。
对于消息队列,只需要两个方法: 生产 和 消费。
具体的业务场景是任务队列,代码设计如下:
同时支持多个队列,每个队列都应该有个名字。final确保TaskQueue是线程安全的。TaskQueue的实现类也应该确保线程安全。
addTask向队列中添加一个任务。队列中仅保存任务的id,不存储任务的业务数据。
popTask从队列中取出一个任务来执行。
这种设计不是特别友好,因为她需要调用者自行保证任务执行成功,如果执行失败,自行确保重新把任务放回队列。 无论如何,这种机制是可以工作的。想想奥卡姆剃刀法则,我们先按照这个设计实现出来看看。
如果调用者把业务数据存在数据库中,业务数据中包含“状态“列,标识任务是否被执行,调用者需要自行管理这个状态,并控制事务。
popTask采用阻塞方式,还是非阻塞方式呢?
如果采用阻塞方式,队列中没任务的时候,客户端不会断开连接,只是等。
一般情况下,客户端会有多个worker抢着干活儿,几条狼一起等一个肉包子,画面太美。连接是重要资源,如果一直没活儿干,先放回池里,也不错。
先采用非阻塞的方式吧,如果队列是空的,popTask返回null,立即返回。
2、后续可能提供的功能
2.1、引入Task生命周期概念
应用场景不同,需求也不同。
在严格的应用场景中,需要确保每个Task执行“成功“了。
对于上面提到的popTask后不管的“模式“,这是另外一种“运行模式“,两种模式可以并行存在。
在这种新模式下,Task状态有3种:新创建(new,刚调用addTask加到队列中)、正在执行(in-process,调用popTask后,调用finish前)、完成(done,执行OK了,调用finishTask后)。
调整后的代码如下:popTask()一次取出一个任务,太磨叽了。
好比我们要买5瓶水,开车去超市买,每去一次买1瓶,有点儿啥。
我们需要一个一次取多个任务的方法。