前一篇文章提到,我選用 ExecutorService 的主因是比較好控制 Thread
而控制的方法是把要產生的 Thread 都加入到我指定的一個 ThreadGroup
如此一來我只要用 ThreadGroup.activeCount() 就可以知道定時執行產生的 Thread 還有幾個正在執行
也可以用 Thread.enumerate(new Thread[ ]) 把 ThreadGroup 中的 Thread 列舉出來。
參考資料:How to use ThreadFactory in Java
產生 ExecutorService 的程式碼如下:
// Initial a thread group ThreadGroup group = new ThreadGroup("GroupName"); // Initail a ExecutorService with ThreadFactory ExecutorService executor = Executors.newSingleThreadExecutor(new MyThreadFactory(group, "ThreadName"));
其中 ThreadFactory 如下:
import java.util.concurrent.ThreadFactory; public class MyThreadFactory implements ThreadFactory { private int count; private String prefix; private ThreadGroup group; public MyThreadFactory (ThreadGroup group, String prefixString) { this.count = 0; this.prefix = prefixString; this.group = group; } @Override public Thread newThread(Runnable r) { return new Thread(this.group, r, this.prefix + "-" + this.count++); } }
如此一來,ThreadFactory 就可以依照我希望的
把 ExecutorService 產生的 Thread 產生在我指定的 ThreadGroup 裡,方便程式日後的存取和監控。
另外需要注意的是,目前有發現如果是 web application 的話
ExecutorService 要記得在網站關閉但伺服器不關閉的時候(例如重新佈署網站)把 ExecutorService 關掉
否則 ExecutorService 產生的 Thread 預設是不會在 web application 被 un-deploy 時自動關閉,會產生 memory leak 的問題。
關閉 ExecutorService 的語法是:
executor.shutDownNow();
而要關閉 ThreadGroup 內的 Thread 時,似乎直接呼叫 ThreadGroup 的 interrupt() 無效?
我的解法是用 enumerate() 列舉出 ThreadGroup 內的所有 Thread
再用迴圈一個一個呼叫它的 interrupt()
不過當然程式中必須隨時要有檢查是否 interrupt 的確認
Java 中 Thread 的 InterruptException 只會發生在 wait 狀態
其他狀態中只是 isInterrupt 會被設為 true,但 Thread 並不會馬上就中斷
要依靠程式碼自行跳脫到 run() 的最底端,讓 Thread 自然結束。
有關如何安全關閉 Thread,可以參考:How to Stop a Thread or a Task
沒有留言:
張貼留言