Java:停止运行时间过长的线程?

时间:2010-03-22 22:07:29

标签: java multithreading

说我有类似的东西

public void run(){
    Thread behaviourThread = new Thread(abstractBehaviours[i]);
    behaviourThread.start();
}

我想等到abstractBehaviours [i] run方法已经完成或运行5000毫秒。我怎么做? behaviourThread.join(5000)似乎没有这样做afaik(我的代码出了问题,我已经把它归结为那个)。

所有抽象的abstractBehaviour类当然都是Runnable。我不想在每个run方法中实现它,因为它看起来很丑陋并且有许多不同的行为,我更愿意在调用/执行线程中使用它并且只执行一次。

解决方案?第一次做这样的线程。谢谢!

编辑:因此中断解决方案将是理想的(需要对AbstractBehaviour实现进行最小的更改)。但我需要线程停止,如果它已经完成或已经过了5000毫秒,所以类似下面的东西将无法工作,因为线程可能在父线程中的while循环之前完成。合理?任何解决这个问题的方法,我都很乐意从明确启动线程的线程中做到这一点。

long startTime = System.currentTimeMillis();
behaviourThread.start();
while(!System.currentTimeMilis - startTime < 5000);
behaviourThread.interrupt();
try {
    behaviourThread.join();
} catch (InterruptedException e1) {
    e1.printStackTrace();
}

编辑:没关系我看到有一个Thread.isAlive()方法,所有解决的我认为

4 个答案:

答案 0 :(得分:6)

执行此操作的最佳方法是使用线程中断机制。工作线程/ Runnable需要定期调用Thread.interrupted()以查看是否该停止。等式的第二部分是一个单独的线程需要在5000毫秒过后在工作线程上调用Thread.interrupt()

使用线程中断(使用标志的定制解决方案)的优点包括:

  • interrupted()状态始终可用于当前线程。您不需要传递对象句柄或使用单例。
  • 中断将取消阻止某些阻塞IO和同步请求。一个定制的解决方案无法做到这一点。
  • 第三方Java应用程序和库可能会尊重Thread.interrupt()

编辑 - 正如评论者指出的那样,您可以使用Thread.interrupted()Thread.currentThread().isInterrupted()来测试当前线程是否已被中断。两种方法的主要区别在于前者清除了中断的标志,但后者没有。

答案 1 :(得分:3)

你不能从run方法外部执行此操作 - run方法必须检查某个变量以查看它是否应该退出。例如:

class InterruptableRunnable implements Runnable
{
   private volatile boolean stop;
   public setStop() {
       stop = true;
   }

   public void run() {
        while (!stop)
        {
            //do some work and occassionaly fall through to check that stop is still true
        }
   }
}

关键是运行循环中的代码偶尔会检查停止标志。然后,您可以连接一个计时器,在5000毫秒后将stop设置为true。

最后,最好不要直接使用Threads,使用优秀的Concurrency Framework。 Concurrency Tutorial是一个很好的起点,书籍Java Concurrency in practice非常出色。

答案 2 :(得分:1)

您可以使用java.util.concurrent包。

    ExecutorService service = Executors.newCachedThreadPool();
    Future future = service.submit(behaviourThread);

    long startTime = System.currentTimeMillis();
    while (!future.isDone()) {
        if (System.currentTimeMillis() - startTime > 5000) {
            future.cancel(true);
            break;
        }
    } 
    // TODO: more work here

    //don't forget to shutDown your ThreadPool
    service.shutDown();

此代码将在5秒后停止您的线程,如果它到那时还没有完成它的工作。如果您选中 behaviourThread.isAlive() ,则会显示 false

答案 3 :(得分:-1)

您可以通过实施Runnable

来实现
public void run()
{
  long time = System.nanoTime(),
       end  = time + 5 000 000 000; // just better formatting
  do {
    ...my code

  } while (System.nanoTime() < end && myOwnCondition);
}
  • 中断不是一个很好的解决方案,因为你需要从外部访问线程 它扰乱了程序流程。线程可以随时在您的代码中终止 使清理变得困难。请养成让线程运行到最后的习惯,否则会打开令人讨厌且难以处理的错误。

  • 如果您的程序太重,以至于在任务完成之前您不知道到达终点,我建议使用标记的中断:

    do {
      breakout:
      {
        ..my code
        if (timetest)
          break breakout;      
      }
      // cleanup
      ...
    } while (...);