簡體   English   中英

如何在java中殺死一個好的線程?

[英]How to kill a thread nice in java?

一個常見的問題,但我沒有找到任何可接受的答案。

我最近遇到了如何以一種很好的方式殺死一個線程的問題。 我嘗試創建一個接受runnables的通用消息處理程序。 問題是我無法以足夠快的速度退出當前的runnable。

runnables中的代碼是未知的,即jni,純java,3:rd部分lib等。下面是一個簡單的例子,睡眠“鋼化”中斷所以線程永遠不會退出(足夠快):我不能夠在任何時候中斷線程,只在每個任務之間是不可接受的。 我的第一個想法是使用thread.stop但不推薦使用。

制片人:

int i = 0;
MessageHandler handler = new MessageHandler();
handler.start();

handler.post(new Runnable() {
    @Override
    public void run() {
        System.out.println("task -" + i++ + " " + Thread.currentThread().getName());
        for (int r=0;r<1000000000;r++) {
            System.out.println("task -" + i++ + " " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});

try {
    Thread.sleep(500);
} catch (InterruptedException q) {
    q.printStackTrace();
}
handler.interrupt();

消費者(MessageHandler):

package test;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class MessageHandler extends Thread implements Runnable {

    private BlockingQueue<Runnable> msgQue = new LinkedBlockingQueue<Runnable>();
    private final static String TAG = "MessageHandler";

    public void run() {
        try {
            System.out.println(TAG + " Initialized "  + currentThread().getName());
            while(true) {
                Runnable task = msgQue.take();
                task.run();
                if (isInterrupted()) {
                    break;
                }
            }
        } catch (InterruptedException e) {
            System.out.println(TAG + " InterruptedException "  + currentThread().getName());
        } finally {
            System.out.println(TAG + " Exit "  + currentThread().getName());
            msgQue.clear();
            msgQue = null;
        }
    }

    public void post(Runnable task) {
        System.out.println(TAG + " post " + currentThread().getName());
        msgQue.add(task);
    }
}

我覺得自己就像一個沒有任何超能力的超人......

嘿,甲骨文給了我力量!

看看這個常見問題解答他們為什么棄用Thread.stop()以及改為使用什么。 它的要點是使用Thread.interrupt()

不,JVM沒有安全的方法來終止任意線程。 請參閱有關這些問題的討論:

我通過使用守護進程解決了這個問題(“一個線程是守護進程”意味着一旦它的父威脅結束就會被終止):我創建了一個可運行的類來控制所需的runnable類。

class Interruptable implements Runnable {
    private Threat t;
    public Interruptable(Threat t) {
        this.t = t;
        this.t.setDeamon(true); //this is the important line
    }
    public void run() {
        this.t.start();
        while(true) {
            try {
                Thread.sleep(1);
            }
            catch(InterruptedException ex) {
                break;
            }
        }
    }
}

現在,當可中斷線程結束時(通過調用中斷方法)子威脅如果被終止也是因為它是一個守護進程。

PS:我不知道怎么寫威脅或線程,我懶得去谷歌:)

您可以停止中斷線程,這兩種解決方案都不是完美的:

  1. 停止只是殺死它,但不僅它可以使外部資源處於不一致狀態(未封閉等),它還可能使程序的數據結構處於不一致狀態。 請參閱Java Thread Primitive Deprecation 這可能非常嚴重,例如,可能會在某些核心庫中創建不一致,並可能在整個應用程序中引起問題。
  2. 中斷不會阻止線程,直到它檢查它(或某些方法拋出InterruptedException ,必須明確捕獲)。 因此,如果一個線程沒有檢查他的中斷狀態,它可能會一直運行。

一般來說,1被認為更糟糕,所以這就是它被棄用的原因。

如何解決困境沒有理想的方法。 要么中斷線程以使它們正常退出,然后它們可以忽略中斷,或者你突然終止它們,然后就不能進行清理。

一種可能性如何以某種方式獲得兩者的最佳效果是中斷線程,等待幾秒鍾,然后突然停止它。 但我不推薦它,停止只是不安全。

另一種可能性是在單獨的進程中啟動任務。 這很復雜,您需要配置可執行路徑,不同平台可能表現不同等等。但是這些流程將完全獨立於您的應用程序,您可以安全地終止它們並讓操作系統進行所有必要的清理。

通過您嘗試停止的代碼的合作,您可以使用您想要的任何機制來完成它。 如果沒有該代碼的合作,停止一個線程將無濟於事。 如果該線程與其他線程協調怎么辦? 如果那個線程導致真正的工作完全在另一個進程中完成怎么辦?

這確實是一個乏味的問題。 我可能會因為我要說的而被投票,但我相信這種對Thread.stop恐懼有時候並不存在。

既然你提到你知道要停止的代碼是做什么的,那么如果你能確定,如果突然停止,它就不會留下任何懸掛資源(文件,套接字等),不會導致任何形式數據損壞或不會導致任何其他線程出現故障,那么在我看來使用Thread.stop是完全安全的。

您應該只使用ExecutorService並向其提交任務,而不是使用隊列和線程。

如果要停止,可以使用shutdown()方法。

您可以使用stop(),前提是您了解它被棄用的原因。 它工作得很好,但可能有副作用。 即你已經知道你在做什么來使用它。

BTW:這不會中斷JNI呼叫。 如果你需要它,你必須啟動一個單獨的進程,你kill -9 ,以確保它會死。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM