繁体   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