2012-09-21 36 views
3

以下片段来自一个测试Sorter的4个不同实现的JUnit测试用例。它调用唯一的方法Sorter已有viz sort()在Java中杀死一个不合作的线程

我想杀死排序过程,如果它花费的时间比说2秒(因为我不在乎任何实施需要超过2秒到sort()比如说500000 Integers)。

我是新的Java多线程,在看过所有其他线程(How to kill a java thread?和其他一些)后,我想到了解决我的问题。 问题是,它会一直工作,还是会有任何问题?我不在乎数组或它的内容,因为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。 A Process可能会被杀死。
    • 显然参数传递在这种情况下并不容易,因为它涉及到一些IPC。
+0

+1,可以得到你想要的是什么,但解决的办法是有趣的。奇怪的是,我期待着你会发布一个答案或其他人。我知道2种方法:)它预计“不可能杀死hava线程”,它可以做你所需要的:多种解决方案! – 2012-09-21 19:26:19

+0

你能摆脱孤儿吗?将其优先级设置为最低可能级别并忘记它?如果你愿意的话,你可以开始另一种方式,而旧方法不应该太多干预。 –

+0

@ Everyone:如果我上面写的任何内容(--edit:answer--)是错误的,请评论/编辑。谢谢。 – Kashyap

回答

3

从您提到的其他问题可能已经看到,不可能在没有合作的情况下可靠地停止Java线程,因为interrupt() ony在线程对其进行测试时有意或无意地工作。

不过,可能杀死一个process。如果你在一个单独的过程中产生每个排序算法,那么你可以强行杀死它。

的缺点是与过程的交互是比使用一个线程交互显著更难,因为你没有共享变量。

+0

谢谢。虽然每个人都给出了正确的答案,但接受了这个答案,因为它实际上提供了一个使用'Process'对象的替代方案 – Kashyap

2

将它始终工作,或可能有任何问题?

它会工作,除非你需要正确处理线程中断。 thread.interrupt()只有在sort方法支持它时才会起作用。我怀疑该方法不会调用Thread.sleep()wait()或其他此类方法。因此,需要测试,看它是否已被中断,因为它做了处理:

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

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

+0

将优先级设置为尽可能最低并忘记它有什么问题吗?没有在Java中尝试过 - 可行吗? –

+0

即使使用最低设置,线程也会消耗会影响@Martin其他性能测量的周期。如果有多个CPU,它将继续在另一个会影响时序的处理器上运行。 – Gray

+0

只有那些在其他优先级较高的线程之后留下的线程才会被阻止? –

3

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

3

这可以是用于使用Thread.stop的情况下()。请阅读javadoc中的免责声明,特别是:

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

+0

你可能是对的。在这种特殊情况下,在数组上运行排序的情况下,它可能是安全的。 –

+0

如果线程被认为是行为良好并且合作的,那么没有理由杀死它 - 线程在被问到时会停止。如果这个推定不成立,Thread.stop()是不安全的。 – JimN

+1

这不是很好的表现和合作。这正是OP的问题!在这种情况下,假设就地排序,没有额外的内存分配(可能需要合并排序),这可能是一个有效且安全的答案。我打算加强它,因为理解这可能是这种情况下最好的解决方案。 –