這個虛類是kafka.network.Acceptor和kafka.network.Processor的父類,提供了一個抽象的Sever執行緒。
它的有趣之處在於為子類的啟動和停止提供了執行緒間的協作機制。
當子類的shutdown方法被呼叫時,子類可以得知自己被停止,在子類做了適當的處理和清理後,呼叫自己的shutdownComplete方法,使得對子類shutdown方法的呼叫從阻塞狀態返回,從而使呼叫執行緒得知子類的物件已經恰當的停止。
即,在另一個執行緒中要關閉一個AbstractServerThread,可以執行它shutdown方法,當此方法從阻塞中返回,代表它已經恰當的關閉。
同樣,對子類的awaitStartup方法呼叫也會阻塞,直到子類確認自己完全啟動,這個方法呼叫才會返回。
這些功能是通過對CountdownLatch和AtomicBoolean的使用來實現的。
private[kafka] abstract class AbstractServerThread extends Runnable with Logging { protected val selector = Selector.open(); private val startupLatch = new CountDownLatch(1) private val shutdownLatch = new CountDownLatch(1) private val alive = new AtomicBoolean(false) /** * Initiates a graceful shutdown by signaling to stop and waiting for the shutdown to complete */ def shutdown(): Unit = { alive.set(false) selector.wakeup() shutdownLatch.await } /** * Wait for the thread to completely start up */ def awaitStartup(): Unit = startupLatch.await /** * Record that the thread startup is complete */ protected def startupComplete() = { alive.set(true) startupLatch.countDown } /** * Record that the thread shutdown is complete */ protected def shutdownComplete() = shutdownLatch.countDown /** * Is the server still running? */ protected def isRunning = alive.get /** * Wakeup the thread for selection. */ def wakeup() = selector.wakeup() }
由於它代表了一個Server執行緒,在其內部使用了java.nio的Selector。所以在shutdown時,需要呼叫Selector的wakeup方法,使得對Selector的select方法的呼叫從阻塞中返回。
繼承它的子類必須對isRunning進行判斷,來確定自己是否已經被要求關閉。以及在處理關閉請求後,呼叫shutdownComplete()來確認已完閉完成。
由於Acceptor和Processor的實現太長,這裡寫了一個例子模擬它們
private class Processor extends AbstractServerThread { override def run() { while(isRunning) { println("processor is running") //執行一些操作 Thread.sleep(1000) } shutdownComplete() } }
在工作迴圈中判斷isRunning作為退出迴圈的條件。然後執行shutdownComplete, 這時對Processor 的shutdown方法的呼叫才會返回。