簡體   English   中英

用Java殺掉一個不合作的線程

[英]Kill an uncooperative thread in Java

以下部分來自JUnit測試用例,該測試用例測試4種不同的Sorter實現。 它調用了Sorter具有的唯一方法Sorter sort()

如果需要的時間超過2秒,我想要終止排序過程(因為我不關心任何需要超過2秒才能sort()說500000 Integers )。

我是新的Java多線程,在查看了所有其他線程( 如何殺死一個java線程?以及其他幾個)之后,我認為以下是我的問題的解決方案。 問題是,它是否能夠始終如一地運作,還是會出現任何問題? 我不關心數組或它的內容,因為reset()會重置它的內容。

我稱之為不合作的原因是因為s.sort()不受我的控制。

protected E[] arr;
@Test
public void testSortTArray() {
    boolean allOk = true;
    for (Sorter s : TestParams.getSorters()) {
        System.out.println("Testing: " + s.getName() + " with " + arrayLenToTestWith + " elems of type "
                + classOfElemType.getName());
        reset();
        long startTime = System.nanoTime();
        MyThread test = new MyThread(s, arr);
        test.start();
        try {
            test.join(TestParams.getTimeThreshold());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (test.isAlive())
            test.interrupt();

        if (!test.isInterrupted()) {
            System.out.println("Time taken: " + ((System.nanoTime() - startTime) / (1000000)) + "ms");
            if (!isSorted(arr)) {
                allOk = false;
                System.err.println(s.getName() + " didn't sort array.");
            }
        } else {
            allOk = false;
            System.err.println(s.getName() + " took longer than .");
        }
    }
    assertTrue("At least one algo didn't sort the array.", allOk);
}

public class MyThread extends Thread {

    private Sorter s;
    private E[] arr;

    public MyThread(Sorter s, E[] arr) {
        this.s = s;
        this.arr = arr;
    }

    @Override
    public void run() {
        s.sort(arr);
    }
}

---編輯:回答---

基於每個人的評論:

  • 不。我正在做的事情並不安全,因為Thread.interrupt()不會掛起線程,它只是設置它的中斷狀態,如果沒有被線程的run()實現檢查,它就沒用了。
    • 在這種情況下,下一個Sorter的sort()將在同一個數組上調用(它仍然由舊的“中斷”線程進行排序),從而使事情變得不安全。
  • 一種選擇是創建一個單獨的Process而不是Thread 一個Process可以被殺死。
    • 顯然,在這種情況下參數傳遞並不容易,因為它涉及一些IPC。

正如您可能從您提到的其他問題中看到的那樣,如果沒有它的合作就不可能可靠地停止Java線程,因為如果線程測試它(故意或無意),則interrupt() ony可以工作。

但是,可以殺死進程 如果您在單獨的進程中生成每個排序算法,那么您可以強制終止它。

缺點是與進程交互比使用線程進行交互要困難得多,因為您沒有共享變量。

沒有線程的合作,沒有可靠和安全的方法來阻止它。 通過線程的協作,您可以使用它支持的機制中斷或停止線程。 線程只是不提供這種隔離......你必須使用多個進程。

這可能是Thread.stop()的一種情況。 盡管如此,請閱讀javadoc中的免責聲明:

不推薦 這種方法本質上是不安全的。 使用Thread.stop停止一個線程會導致它解鎖它已鎖定的所有監視器(這是未經檢查的ThreadDeath異常向上傳播的自然結果)。 如果先前受這些監視器保護的任何對象處於不一致狀態,則受損對象對其他線程可見,可能導致任意行為。 stop的許多用法應該被簡單修改某個變量的代碼替換,以指示目標線程應該停止運行。 目標線程應該定期檢查此變量,並且如果變量指示它將停止運行,則以有序的方式從其run方法返回。 如果目標線程等待很長時間(例如,在條件變量上),則應使用中斷方法來中斷等待。

它會一直工作,還是會有任何問題?

它可以工作,除了你需要正確處理線程中斷。 thread.interrupt()僅在sort方法支持時才有效。 我懷疑該方法不會調用Thread.sleep()wait()或其他此類方法。 因此,它需要測試它是否在處理過程中被中斷:

 while (!Thread.currentThread().isInterrupted()) {
     // do sort stuff
 }

如果不這樣做,那么中斷線程將不會停止處理。 我當然會添加另一個test.join(); 在中斷之后,確保線程在您開始另一個排序操作之前完成。

暫無
暫無

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

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