使用 Thread 和 Thread.sleep 更改周期性运动的间隔

Changing intervall of periodic action with Thread and Thread.sleep

我有一个周期性的动作,我想在定义的时间间隔内(以秒为单位的粒度)执行。所以我使用了一个线程,它在请求的时间内休眠,然后执行操作,然后再次休眠等等。

  public class DiscoveryThread extends Thread
  {
    private int deviceDiscoveryIntervall = 1;

    public void setDeviceDiscoveryIntervall(int seconds)
    {
       deviceDiscoveryIntervall = seconds;
    }

    @Override
    public void run()
    {
      while(!isInterrupted())
      {
        //do there the action

        try 
        {
          sleep(deviceDiscoveryIntervall*1000);
        } 
        catch (InterruptedException e) 
        {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

    }
  }

现在我想有时为定期操作设置一个新的间隔。如果 intervall 在 10 秒之前,我将它设置为最后一个动作后 5 秒到一秒,无论如何我必须等待 5 秒直到下一个动作,但在这种情况下它应该立即执行该动作。

那么我应该怎么做呢?如果我使用 interrupted() 方法,睡眠方法将抛出 InterruptedException 并且我可以立即执行操作。但是后来我必须为整个循环使用自己的标志,因为我不想退出线程。在 InterruptedException 之后再次调用 sleep() 方法如何,中断标志是否仍然设置?我可以再次中断 sleep() 方法吗?以及如何使用 interrupted() 方法来不停止线程,这不是一种误用吗?

线程应该等待具有正确超时的对象,当您希望线程提前唤醒时调用对象上的 notifyAll

尽管如此,您应该考虑使用 ScheduledExecutorService 而不是尝试自己动手。

使用 ScheduledExecutorService:

private final Runnable r = new Runnable() {
    @Override
    public void run() {
        // ...
    }
};

private final ScheduledExecutorService ses = 
    Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> sf = ses.scheduleAtFixedRate(r, 0, 10, TimeUnit.SECONDS);

// change to 5 sec: cancel and reschedule
sf.cancel();
sf = ses.scheduleAtFixedRate(r, 0, 5, TimeUnit.SECONDS);