3

以下部分来自一个 JUnit 测试用例,它测试了Sorter. 它调用的唯一方法Sorter有 viz sort()

如果排序过程花费的时间超过 2 秒,我想终止排序过程(因为我不关心任何花费超过 2 秒才能sort()说 500000的实现Integers)。

我是 Java 多线程的新手,在查看了 SO 上的所有其他线程(如何杀死 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()实现没有检查,那是没用的。
    • 在这种情况下,下一个排序器的 sort() 将在同一个数组上调用(仍然由旧的“中断”线程排序),从而使事情变得不安全。
  • 一种选择是创建一个单独Process的而不是Thread. AProcess可以被杀死。
    • 显然,在这种情况下传递参数并不容易,因为它涉及一些 IPC。
4

4 回答 4

3

正如您可能从您提到的其他问题中看到的那样,如果没有 Java 线程的合作,就不可能可靠地停止它,因为interrupt()只有在线程对其进行测试时(有意或无意地)才有效。

但是,可以杀死一个进程。如果您在单独的进程中生成每个排序算法,那么您可以强行杀死它。

缺点是与进程交互比与线程交互要困难得多,因为您没有共享变量。

于 2012-09-21T19:26:03.670 回答
3

没有线程的合作,就没有可靠和安全的方法来阻止它。通过线程的协作,您可以使用线程支持的机制来中断或停止线程。线程只是不提供这种隔离......你必须使用多个进程。

于 2012-09-21T19:28:16.700 回答
3

这可能是 Thread.stop() 的情况。不过,请阅读 javadoc 中的免责声明,尤其是:

已弃用. 这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常沿堆栈传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。停止的许多用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则以有序的方式从它的run方法返回。如果目标线程等待很长时间(例如在条件变量上),则应使用中断方法来中断等待。

于 2012-09-21T19:40:13.687 回答
2

它会始终如一地工作,还是会出现任何问题?

除了您需要正确处理线程中断外,它会起作用。 thread.interrupt()仅当该sort方法支持时才有效。我怀疑该方法不会调用Thread.sleep(),wait()或其他此类方法。因此它需要测试它是否在处理过程中被中断:

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

如果它不这样做,那么中断线程将不会停止处理。我肯定会test.join();在中断之后添加另一个,以确保线程在您开始另一个排序操作之前完成。

于 2012-09-21T19:21:54.893 回答