首先,說下我的需求。我有一個子線程對局域網某個主機進行試探連接,用的是開源項目JCIFS類,該類並沒有對連接超時時間的設置,只是在很長時間連不上後會報出connect timeout的warning,這並不是我想要的。因爲試想,用戶可能會在一段時間連不上後選擇退出該Activity,那麼此時後臺還在連接,當連接上後會在子線程通過handler將數據傳回,或者連接不上後通過handler傳一個消息,以彈出dialog提示無法連上。可是,此時Activity已經退出,數據或者dialog所依存的Activity已經退出,這樣的話就會報異常(具體什麼異常忘記了)。
接下來,說下我是怎麼解決的。我聲明一個boolean類型的成員變量isExited,默認爲false。
該變量在該Activity的onDestroy時變爲true。當需要handler傳消息給主線程時先判斷isExited是false還是true,如果false才進行相應操作。子線程不管他,讓他自行運行結束。
你可能會有這樣的疑問,這樣Activity退出時並不能結束子線程啊?當然,我一開始也試着去結束他,控制他同主線程一起結束。可是,要知道,Java中線程之間是平等的,所謂的主線程子線程只是一個區分而已,一個線程並不能強制的控制另外一個線程何時結束,最好的結束方式就是讓子線程的run方法運行完畢。這也就是Thread.stop()和Thread.destroy()不能使用的原因。另外,網上有說通過InterruptedException來結束的方案,對於我這個例子卻是不適用的,因爲只有Thread.sleep()或Thread.wait()被打斷時纔會拋出該異常,對於阻塞的操作,無法適用。
以下是我在網上查到的三種結束方式:
1.線程正常執行完畢,正常結束 ,線程正常執行完畢, 也就是讓 run 方法執行完畢,該線程就會正常結束。
2.監視某些條件,結束線程的不間斷運行 ,監視某些條件, 然而,常常有些線程是伺服線程。它們需要長時間的運行,只有在外部某些條件滿足的情況 下,才能關閉這些線程。 通常,它們執行在一個 while(true)的死循環中。如:
@Override
publicvoid run() {
while (true) {
someWork();
if (finished) {
break;
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) { /* TODO 自動生成 catch 塊 * */
e.printStackTrace();
}
}
}
3.捕獲 InterruptedException 運行時異常,中斷當前線程 , 運行時異常, 有些執行伺服任務的線程,在 while(true)這樣的死循環內部,是一個阻塞中的方法。此時, 就不能採用第二種方法了。因爲,當該方法沒有返回時,該線程一直處於阻塞當中,根本無 法執行其他語句。 此時,就需要調用該線程的 interrupt 方法,產生一個 InterruptedException 運行時異常,是 阻塞中的那個方法拋出這個異常,從而讓我們有機會結束這個線程的執行。如:
@Override
public void run() {
while(true){
try {
someMethod();//此處爲阻塞的方法
} catch (InterruptedException e1) {
thrownew RuntimeException(); //或者 break;
}
someWork();
}
}
}
一個外部的 Thread 對象指向這個線程。需要結束這個線程時,只需要調用 thread 對象的 interrupt() 方法,就會在 someMethod()這條語句中產生一個 InterruptedException 異常,從而結束該線程的阻塞狀態,通過拋出異常,或者 break 跳出死循環,結束這個線程。