Java旬昭。遇到一個(gè)問題。需要停止一個(gè)運(yùn)行時(shí)的模塊T
模塊T里又分了子模塊ABCDE
每個(gè)子模塊都有自己的線程池
T是一個(gè)被調(diào)用的角色煌贴。
然后我可以確定的是每個(gè)子模塊的線程池的submit肯定是要去調(diào)用
另一個(gè)模塊J的(這點(diǎn)非常重要)
T被觸發(fā)后逗余。ABCDE之間會(huì)有數(shù)據(jù)輪轉(zhuǎn)。當(dāng)然還有鎖的使用
現(xiàn)在外部調(diào)用方判斷T需要停止泽腮。然后重置。再重新調(diào)用衣赶。
我一開始以為很簡(jiǎn)單啊诊赊。把變量設(shè)置成null。然后重新new不就完了么府瞄。
然后用jstack 發(fā)現(xiàn)線程還在碧磅。數(shù)據(jù)也還在。遵馆。鲸郊。而且這些線程感覺就要很久之后才會(huì)被回收了(因?yàn)橐萺un方法全部執(zhí)行完。然后系統(tǒng)gc货邓。秆撮。)。因?yàn)槲矣玫氖蔷€程池换况。
然后我又去了解了一下shutdown职辨。shutdownNow和isTerminated 3個(gè)方法
結(jié)合我自己的代碼。我說一下我的方法把
因?yàn)槲业逆i是我自己用atomicBoolean封裝的一個(gè)單獨(dú)的類复隆。
所以我可以控制是不是真的要用到鎖拨匆,如果用lock的可能就還需要處理lock姆涩。
我ABCDE這些子模塊都有父類挽拂。創(chuàng)建線程池的方法是在父類里的。
我用的一般就是newFixedThreadPool和newSingleThreadExecutor骨饿。這2個(gè)
所以我就自定義了一個(gè)類重寫了這2個(gè)方法亏栈。再自定義了一個(gè)類(AThreadPoolExecutor)繼承自ThreadPoolExecutor.重寫了submit和execute這2個(gè)方法台腥。
@Override
public Futuresubmit(Runnable task) {
try{
return super.submit(task);
? ? }catch (RejectedExecutionException executionException){
}
return null;
}
@Override
public Futuresubmit(Runnable task, T result) {
try{
return super.submit(task, result);
? ? }catch (RejectedExecutionException executionException){
}
return null;
}
@Override
public Futuresubmit(Callable task) {
try{
return super.submit(task);
? ? }catch (RejectedExecutionException executionException){
}
return null;
}
@Override
public void execute(Runnable command) {
try {
super.execute(command);
? ? }catch (Exception e){
if (einstanceof InterruptedException){
}else {
throw? e;
? ? ? ? }
}
}
類似這樣。這樣就保證我在停止的時(shí)候碰到提交和中斷就不會(huì)出問題绒北。(因?yàn)橥饷鎠ubmit的地方實(shí)在太多了黎侈。。改不過來(lái))
然后呢闷游。我直接去調(diào)用每個(gè)線程池的shutdownNow峻汉。把所有未執(zhí)行的任務(wù)都去除。
然后因?yàn)槊總€(gè)submit的內(nèi)容都是要去調(diào)用J的脐往。照著模塊之間調(diào)用你起碼要封裝一層的做法
所以我在判斷我要停止的時(shí)候休吠。直接在調(diào)用J的那個(gè)地方去判斷了線程的狀態(tài)
if (Thread.currentThread().isInterrupted()){
throw? new InterruptedException(Thread.currentThread().getName());
}
return super.run(log,o,method,objects,methodProxy);
就像這樣。這就能保證我所有的submit都能被很快的處理完(這當(dāng)然是因?yàn)榈膕ubmit里沒有啥while啊for啊這種耗時(shí)循環(huán)這種)
然后剩下的就簡(jiǎn)單了业簿。
把線程池重開就完事瘤礁。
重開的時(shí)候判斷下isTerminated
如果是false。梅尤。我現(xiàn)在的做法就是先打個(gè)警告log柜思。發(fā)現(xiàn)再來(lái)排查問題。