我有一個ThreadPoolExecutor,當我調用getActiveCount()時,它似乎對我撒謊。然而,我沒有做很多多線程編程,所以也許我做了一些不正確的事情。ThreadPoolExecutor的getActiveCount()
這裏是我的TPE
@Override
public void afterPropertiesSet() throws Exception {
BlockingQueue<Runnable> workQueue;
int maxQueueLength = threadPoolConfiguration.getMaximumQueueLength();
if (maxQueueLength == 0) {
workQueue = new LinkedBlockingQueue<Runnable>();
} else {
workQueue = new LinkedBlockingQueue<Runnable>(maxQueueLength);
}
pool = new ThreadPoolExecutor(
threadPoolConfiguration.getCorePoolSize(),
threadPoolConfiguration.getMaximumPoolSize(),
threadPoolConfiguration.getKeepAliveTime(),
TimeUnit.valueOf(threadPoolConfiguration.getTimeUnit()),
workQueue,
// Default thread factory creates normal-priority,
// non-daemon threads.
Executors.defaultThreadFactory(),
// Run any rejected task directly in the calling thread.
// In this way no records will be lost due to rejection
// however, no records will be added to the workQueue
// while the calling thread is processing a Task, so set
// your queue-size appropriately.
//
// This also means MaxThreadCount+1 tasks may run
// concurrently. If you REALLY want a max of MaxThreadCount
// threads don't use this.
new ThreadPoolExecutor.CallerRunsPolicy());
}
在這個類中我也有,我進入我的Runnable(FooWorker
)一個DAO,像這樣:
@Override
public void addTask(FooRecord record) {
if (pool == null) {
throw new FooException(ERROR_THREAD_POOL_CONFIGURATION_NOT_SET);
}
pool.execute(new FooWorker(context, calculator, dao, record));
}
FooWorker
運行record
(唯一的非單身人士)通過calculator
通過狀態機然後通過dao
發送轉換到數據庫,如下所示:
public void run() {
calculator.calculate(record);
dao.save(record);
}
一旦我的主線程完成創建新的任務我嘗試和等待,以確保所有線程成功完成:
while (pool.getActiveCount() > 0) {
recordHandler.awaitTermination(terminationTimeout,
terminationTimeoutUnit);
}
我從輸出日誌中看到什麼(這大概是不可靠的,由於線程) getActiveCount()過早返回零,並且while()循環正在退出,而我的最後一個線程仍在打印calculator
的輸出。
注意我也嘗試過撥打pool.shutdown()
,然後使用awaitTermination
,但接下來我的作業運行池仍然關閉。
我唯一猜測是一個線程裏面,當我發送數據到dao
(因爲它是由Spring在主線程中......創造了一個單),JAVA是考慮到線程激活,因爲(我承擔)正在處理/等待主線程。
直覺上,僅基於我所看到的,這是我的猜測。但是......這是真的嗎?如果沒有在run()
的頂部添加手動增量變量並在最後遞減以跟蹤線程數量,有沒有辦法「做到這一點」?
如果答案是「不要通過dao」,那麼我不必爲每個線程「新增」一個DAO嗎?我的過程已經是一個(美麗,高效)的野獸,但這真的很糟糕。
你知道我讀了多少次javadoc並完全忽略了「近似」?有趣的事。我想知道它爲什麼不準確......如果它不可靠,似乎毫無用處。 – inanutshellus
@ Gabriel:它的「近似」原因可能是因爲獲得準確的計數*可能是一項昂貴的操作。 –