【问题标题】:Abort loop after fixed time固定时间后中止循环
【发布时间】:2011-05-03 13:34:52
【问题描述】:

我有一个线程,其中我有一个无限循环,做一些网络工作。看来我每次执行此操作时都没有得到响应,因此线程会挂起几秒钟,这会对我的软件造成严重问题。我需要的是循环的某种“截止日期”,如果需要更多时间(例如 100 毫秒)重新启动。

private boolean active = true;
public void run(){

   while(active){
       //some network stuff e.g:
       dnshandler.reverselookup("8.8.8.8");
   }

}

(这不是真正的课程……只是为了了解我的意思。)

任何想法如何处理这个?

更新: 我按照建议用单独的线程处理它。实际上我使用了 Callable 因为我需要一个返回值。

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        try {
            List<Future<String>> results = executor.invokeAll(Arrays.asList(new CallableClass()), 500), TimeUnit.MILLISECONDS);
            for (Future<String> current : results) {
                if (!current.isCancelled()) {
                    someValue = current.get();
                } else {
                    // timeout
                    executor.shutdownNow();
                }
            }

        } catch (Exception e) {
            //handle it!
            e.printStackTrace();
        }

但我现在面临的问题是,executor.shutdownNow() 没有终止挂起的 Callable 任务(根据文档,这是正确的行为)。有没有办法杀死执行者任务? (我知道这不是一个干净的解决方案,但有些请求是由图书馆处理的)

【问题讨论】:

    标签: java loops concurrency


    【解决方案1】:

    例如,您可以将网络内容放入单独的线程并运行几秒钟:

    int timeoutTime = ...
    Runnable networkingStuff = ... // put the networking in here
    Thread thread =new Thread(networkingStuff);
    thread.start();
    try {
        thread.join(timeoutTime);
        if(thread.isAlive()) {
            thread.interrupt();
        }
    } catch (InterruptedException e) {
        // catch here the interruption
     }
    

    【讨论】:

    • 我没有考虑加入,这可以工作。只是为了确认,如果“网络线程”在timeoutTime 内完成,我最终会进入 try-catch-block 的 try 部分,否则会进入 catch。无论哪种方式,我的无限循环都会继续?
    • 如果线程被异常中断,你最终会进入 catch 块。这不应该在正常工作条件下发生。在 nprmal 条件下,您应该始终以“if (thread.isAlive())”结尾。如果线程自行完成,则 thread.isAlive() == false。如果超时后它仍在运行,则 thread.isAlive() == true 并使用 thread.interrupt() 终止线程。在你的无限循环中,你应该检查 Thread.interrrupted() == true。如果是这种情况,您应该通过调用 break 或设置一个在循环条件中检查的变量来完成循环。
    • 好的,谢谢。我按照你的设想实现了这个,它在本地工作。我会将它添加到下一个测试版本中,并让您知道它在满负荷下是如何工作的。谢谢!
    【解决方案2】:

    Google Guava 的 TimeLimiter 可以满足您的需求。

    [TimeLimiter] 生成代理,对代理对象的方法调用施加时间限制。

    【讨论】:

      【解决方案3】:

      抱歉,因为我不是 Java 开发人员,所以如果这是错误的,但从一般编程的角度来看,您应该让可能需要时间的方法返回某种形式的 TimeoutException

      您可以在循环中捕获它,然后它会自动重新启动。

      这不是循环的问题,更重要的是您在其中调用的方法。

      另一种方法是在单独的线程上运行耗时的操作,这样就不会挂起任何东西。然后,您可以随时通知主 (UI) 线程完成。

      【讨论】:

      • 我想每次调用耗时的方法时都抛出一个线程,因为这是处理阻塞函数的标准方法。但是我有点害怕每秒抛出几百个线程,或者这不是问题吗?无论如何,我将研究 TimeoutException 方法并报告回来。谢谢 :)
      • 在创建线程时您很可能会遇到性能问题。一个更好的主意是在你的线程中包含整个循环,而不是操作。
      • 整个循环已经在一个单独的线程中。我有一个生产者线程和一些消费者线程。提到的线程是消费者线程。如果所有消费者线程由于没有响应而挂起,则会出现问题,这会导致内存不足异常(可以在生产者或消费者之间使用较小的缓冲区来避免这种情况(-->由于生产者无法生产而导致数据丢失)或增加堆大小,这更像是一种解决方法并导致其他问题)。我还在努力赶上TimeoutException... 稍后会发布我的进度。
      • 很公平,抱歉我不能更具体或提供任何代码 - 正如我所说的,我不是 Java 开发人员,只是想提供帮助! ^_^
      【解决方案4】:

      您的无限 while 循环正在占用 CPU。尝试添加 50 毫秒左右的延迟,以便让 CPU 稍作休息以处理其他任务。更好的是,使用TimerTimerTask 来安排您的任务,并有一定的延迟。

      【讨论】:

        【解决方案5】:

        你应该在超时后中断线程。查看java并发tutorial

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-25
          • 2017-08-12
          • 1970-01-01
          • 2018-07-07
          相关资源
          最近更新 更多