使用Thread和Thread.sleep更改周期性操作的间隔

时间:2015-11-12 14:43:41

标签: java multithreading interrupted-exception

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

  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。如果intervall在10秒之前并且我在最后一次操作后5秒钟将其设置为1秒,我必须等待5秒直到下一个动作,但它应该立即执行此操作。

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

2 个答案:

答案 0 :(得分:2)

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

你应该考虑使用ScheduledExecutorService来做这样的事情,而不是试图自己动手。

答案 1 :(得分:1)

使用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);