2012-07-23 248 views
0

我有一个JRuby引擎,它可以评估一些脚本,并且如果它需要超过5秒的时间我想关闭该线程。 我想是这样的:Java线程不会停止

class myThread extends Thread{ 
    boolean allDone = false; 

    public void threadDone() { 
     allDone = true; 
    } 

    public void run() { 
     while(true) { 
      engine.eval(myScript); 
      if(allDone) 
       return; 
     } 
    } 

(...) 

    th1 = new myThread(); 
    th1.start(); 
    try { 
     Thread.sleep(5000); 
     if(th1.isAlive()) 
      th1.threadDone(); 
    } catch(InterruptedException e) {} 

    if(th1.isAlive()) 
     System.out.println("Still alive"); 

我也试图与th1.stop()th1.interrupt()th1.isAlive()方法retured值始终true杀死线程。

我该怎么办? 我想补充myScript可能是“while(1)do; end”,我不能等到它完成。所以我想要阻止这样的脚本,并且如果它花费超过5秒钟就杀死线程。

+0

不要'扩展线程'。这是一个众所周知的反模式。 – 2012-07-23 12:03:31

+0

它正在运行一个脚本,对吧?所以你需要停止它运行脚本。如果将'myScript'设置为null会发生什么?它会立即在线程中引发异常吗? – 2012-07-23 12:58:30

+0

不,它不。如果我将'myScript'设置为“”,它会循环。它表现得像“while(1)do; end”。 – user1521526 2012-07-23 13:13:39

回答

2

另一种解决方案是使用内置的机制来中断线程:

public void run() { 
    while (!Thread.currentThread().isInterrupted()) { 
     engine.eval(myScript); 
    } 
} 

... 
th1 = new myThread(); 
th1.start(); 
try { 
    Thread.sleep(5000); 
    th1.interrupt(); 
} 

这样一来,无需一个allDone领域,未能同步,没有任何风险。

+0

好像你可以把这个条件放入'while'而不是'true'。 – 2012-07-23 12:04:27

+0

是的,我刚刚复制并粘贴了原始代码,但没有太多注意,但我会解决这个问题。 – 2012-07-23 12:06:12

+1

似乎这个习惯用法是检查'Thread.interrupted()',为自己保存一个间接寻址,这个调用也会清除被中断的标志,这应该是很好的 - 只要你发现你被中断了,你重置'interrupt'信号标志(我在前面的问题中读到了这个) – 2012-07-23 12:11:12

0

为了让你的线程可以停止,你可能需要类似的东西。

class MyTask implements Runnable { 
    public void run() { 
     try { 
      engine.eval(myScript); 
     } catch(ThreadDeath e) { 
      engine = null; // sudden death. 
     } 
    }  
} 

您可以调用Thread.stop(),但我建议您先阅读此方法的警告。


如果你想要一个线程运行长达5秒,最简单的解决方案是线程自行停止。

class MyTask implements Runnable { 
    public void run() { 
     long start = System.currentTimeMillis(); 
     do { 
      engine.eval(myScript); 
     } while(System.currentTimeMillis() < start + 5000); 
    }  
} 

这假定您想要重复运行engine.eval()。如果不是这种情况,你可能不得不停止()线程。它有一个很好的理由被弃用,但它可能是您唯一的选择。

+0

Peter我只想运行engine.eval()一次。当用户尝试评估诸如“while(1)do; end”之类的脚本时,就会出现问题。所以我想要防止这种情况发生,如果它需要超过5秒钟的时间就杀死线程。 – user1521526 2012-07-23 13:06:30

+0

在这种情况下,Thread.stop()是你唯一的选择。这可能会让您的引擎处于不一致的状态,因此您可能需要重新创建它。 – 2012-07-23 13:08:33

+0

以及我试图使用Thread.stop()但线程仍然活着。 (Thread.isAlive()方法返回true) – user1521526 2012-07-23 13:15:34