Java如何停止執行緒,確定你知道的都是正確的麼?
回想當年剛開始做Java開發的時候,如何停止執行緒執行可是難倒了一批人,停止執行緒的方法眾說紛紜:
- 呼叫Thread.stop() :
Thread thread = new Thread(){
@Override
public void run() {
for (int i=0; i < 999 && !isCanceled; i++) {
System.out.println("哈哈,我還沒死...");
}
}
};
thread.start();
// kill you now
thread.stop();
點評: 不用多說,直接拉出去斬了
- 執行緒外面定義boolean變數標識為是否已經取消,執行緒裡每個迴圈地方加判斷,變數變成了取消則停止迴圈:
private volatile boolean isCanceled = false;
new Thread(){
@Override
public void run() {
for (int i=0; i < 999 && !isCanceled; i++) {
System.out.println("哈哈,我還沒死...");
}
}
}.start();
// kill thread
isCanceled = true;
點評: 太片面,執行緒裡Thread.sleep(999999)取消不了的
- 通過呼叫interrupt() :
Thread thread = new Thread(){
@Override
public void run() {
sleep(99999);
System.out.println("剛睡醒,我還沒死!!!");
}
};
thread.start();
// kill you now
thread.interrupt();
點評:也是太片面,for迴圈取消不了
以上方案意思是有那麼一點了,只是零零碎碎,如何將兩個方案結合是今天的第一個話題。
在Thread內提供了一個方法叫interrupted(), 其返回值即告知是否執行緒被interrupt()執行過,簡單說:無需自己定義boolean變數,可以用它代替,如果執行緒能被interrupt()而停止正好,如果是內部迴圈操作可以用它作為迴圈停止的條件:
Thread thread = new Thread(){
@Override
public void run() {
for (int i=0; i < 999 && !Thread.interrupted(); i++) {
System.out.println("哈哈,我還沒死...");
}
}
};
其實,還有一種情況是停止不了的,類似socket/http通訊這種不能被interrputted的情況,當然也有巧妙的辦法:過載Thread的interrput()方法:
// 過載interrupt 通過關閉socket起到關閉執行緒的作用
@Override
public void interrupt() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
今天的第二個話題是,使用單個執行緒的情況在專案中極少,很多情況使用執行緒池託管的,那麼執行緒池裡如何停止某個task呢?
JDK5提供了ExecuteService,並通過Executors提供了多個候選的執行緒池選擇方案,ExecutorService提交task有兩種方式:execute()和submit(), 我們這裡對submit()比較感興趣,因為submit()會返回Feature,不管submit的是 Runnable還是Callable都會有Feature返回,Feature物件提供了一系列API,如:
- cancel(boolean mayInterruptIfRunning) ;
- isCanceled();
- get();
- get(long timeout, TimeUnit unit);
- isDone()
看到第一個API,很是讓人興奮,難倒這真的可以一步到位?但很不好意思,依然不行,其實跟第一個話題的原理一摸一樣,如果內部有阻塞執行緒的操作會因此而退出,如: wait(), join(), sleep() 等,但是遇到IO阻塞操作,比如進行socket通訊,僅僅通過呼叫cancel(true)是不行的,不過可以過載interrupt() 關閉socket即可, 遇到大量迴圈也要通過Thread.interrupted()作為迴圈結束的條件:
class Task extends Thread{
private Socket socket;
public Task(){
// init socket
}
// 過載interrupt 通過關閉socket起到關閉執行緒的作用
@Override
public void interrupt() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void func () {
ExecutorService timer = Executors.newCachedThreadPool();
Future<?> future = timer.submit(new Task());
future.cancel(true);
}
好了,夜深了...回憶到此結束
相關文章
- Thinking in Java---如何正確的終止子執行緒ThinkingJava執行緒
- 我們該如何正確的中斷一個執行緒的執行??執行緒
- 轉行轉崗的正確姿勢,你知道嗎?
- springboot 中如何正確的在非同步執行緒中使用requestSpring Boot非同步執行緒
- 面試官:你確定 Redis 是單執行緒的程式嗎?面試Redis執行緒
- 如何正確執行 DORA 指標指標
- 血的教訓--如何正確使用執行緒池submit和execute方法執行緒MIT
- 如何確定Kafka的分割槽數、key和consumer執行緒數Kafka執行緒
- 詳細分析 Java 中啟動執行緒的正確和錯誤方式Java執行緒
- 如何進行正確的 CodeReviewView
- java 停止執行緒Java執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- 併發程式設計系列之如何正確使用執行緒池?程式設計執行緒
- 在共享記憶體中進行執行緒間的同步是確保多執行緒程式正確執行的關鍵,以下是幾種常見的方法記憶體執行緒
- 老師,你確定Java註釋不會被執行嗎?Java
- PHP 互斥鎖:如何確保程式碼的執行緒安全?PHP執行緒
- 如何正確實現 Java 中的 HashCodeJava
- Java中確保執行緒安全最常用的兩種方式Java執行緒
- 併發基礎-第01章-實現執行緒的正確方式執行緒
- MySQL如何計算重要的指標,來確定配置是否正確MySql指標
- 如何正確設定動態TextView的textSizeTextView
- 談談你對 Java 平臺的理解?“Java 是解釋執行”,這句話正確嗎?Java
- 【高併發】通過原始碼深度解析ThreadPoolExecutor類是如何保證執行緒池正確執行的原始碼thread執行緒
- JavaScript中Array方法你該知道的正確開啟方法JavaScript
- java 多執行緒之使用 interrupt 停止執行緒的幾種方法Java執行緒
- 開發函式計算的正確姿勢——執行 Selenium Java函式Java
- Hive SQL語句的正確執行順序HiveSQL
- 如何正確的找BUG
- 多執行緒併發篇——如何停止執行緒執行緒
- 阿里一面:Java中如何停止執行緒?阿里Java執行緒
- 如何正確定義效能瓶頸
- 如何優雅的停止一個執行緒?執行緒
- 再談JavaScript作用域——你確定你真的知道?JavaScript
- 你的專案應該如何正確分層?
- 如何正確使用Java8的Optional機制Java
- 如何正確的建立網站網站
- React 中執行 setState 時怎麼保證你取到的上一次state是正確的?React
- 如何確定敏捷是否適合你的團隊?敏捷