**模板方法模式定义:**定义一个操作中的算法框架,而将一些步骤延迟到子类当中实现,使得一个子类可以不改变算法结构而重定义该算法某些具体的步骤。
DelayedOperation: DelayedOperation是Kafka延迟任务部分代码中延迟任务的抽象基类。延迟操作用来实现Kafka中的一些特殊场景,例如在ack=all的情况下生产者向broker发送数据,由于数据需要在replica中进行同步,所以broker向生产者发送response需要延迟执行,这便是一个延迟操作。
DelayedOperation代码及具体方法含义:
abstract class DelayedOperation(override val delayMs: Long,
lockOpt: Option[Lock] = None) extends TimerTask with Logging {
//标致操作是否完成
private val completed = new AtomicBoolean(false)
//辅助保证多线程情况下的线程安全
private val tryCompletePending = new AtomicBoolean(false)
private[server] val lock: Lock = lockOpt.getOrElse(new ReentrantLock)
/*
* 强制进行延迟操作的算法结构(如果延迟操作没有完成,强制完成延迟操作)
*/
def forceComplete(): Boolean = {
if (completed.compareAndSet(false, true)) {
// cancel the timeout timer
cancel()
onComplete()
true
} else {
false
}
}
/**
* Check if the delayed operation is already completed
*/
def isCompleted: Boolean = completed.get()
def onExpiration(): Unit
/**
* 执行延迟操作,由子类实现
*/
def onComplete(): Unit
/**
* 执行延迟操作,由子类实现
*/
def tryComplete(): Boolean
/**
* 多线程场景下进行延迟操作的算法结构
*/
private[server] def maybeTryComplete(): Boolean = {
var retry = false
var done = false
do {
if (lock.tryLock()) {
try {
tryCompletePending.set(false)
done = tryComplete()
} finally {
lock.unlock()
}
retry = tryCompletePending.get()
} else {
retry = !tryCompletePending.getAndSet(true)
}
} while (!isCompleted && retry)
done
}
override def run(): Unit = {
if (forceComplete())
onExpiration()
}
}
在DelayedOperation的代码中通过maybeTryComplete方法定义了延迟操作的具体算法结构,但其中的步骤tryComplete方法并没有实现,原因在于maybeTryComplete的算法结构是不变的所有的延迟操作执行都是这个逻辑,但tryComplete的逻辑不是固定的,不同的延迟操作完成的逻辑不同。这种实现方法封装了不变的部分,扩展了(在子类)可变的部分,代码的可维护性、扩展性大大增强。