我认为您想要的可以通过以下方式更透明地实现ScheduledExecutorService
:
class PeriodicRunner implements Runnable
{
private final ScheduledExecutorService _scheduler = Executors.newSingleThreadScheduledExecutor();
PeriodicRunner()
{
_scheduler.scheduleWithFixedDelay(this, 5, 5, TimeUnit.SECONDS);
}
public void trigger()
{
_scheduler.execute(this);
}
public void run()
{
System.out.println("some task here");
}
}
更新
例如,以下内容:
PeriodicRunner runner = new PeriodicRunner();
Thread.sleep(TimeUnit.SECONDS.toMillis(12));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("[" + new Date() + "] triggering extra task");
runner.trigger();
将产生输出:
[Wed Mar 20 13:18:31 CST 2013] some task here
[Wed Mar 20 13:18:36 CST 2013] some task here
[Wed Mar 20 13:18:38 CST 2013] triggering extra task
[Wed Mar 20 13:18:38 CST 2013] some task here
[Wed Mar 20 13:18:39 CST 2013] triggering extra task
[Wed Mar 20 13:18:39 CST 2013] some task here
[Wed Mar 20 13:18:40 CST 2013] triggering extra task
[Wed Mar 20 13:18:40 CST 2013] some task here
[Wed Mar 20 13:18:41 CST 2013] some task here
[Wed Mar 20 13:18:46 CST 2013] some task here
更新 2
要扩展 d3rzKy 的答案,修复现有代码,您可以引入一个标志来指示trigger
已被调用。此外,await
不能保证一直等待,因此您需要循环并跟踪您已经等待了多长时间。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;
public class PeriodicRunner implements Runnable {
private final Lock lock = new ReentrantLock();
private final Condition cond = lock.newCondition();
private volatile boolean triggered = false;
public void trigger() {
lock.lock();
try {
triggered = true;
cond.signalAll();
}
finally {
lock.unlock();
}
}
@Override
public void run() {
lock.lock();
try {
while(true) {
if (!triggered) {
long remainingMs = TimeUnit.SECONDS.toMillis(5);
long dueTimeMs = System.currentTimeMillis() + remainingMs;
while (remainingMs > 0 && !triggered) {
if (cond.await(remainingMs, TimeUnit.MILLISECONDS)) {
break;
}
remainingMs = dueTimeMs - System.currentTimeMillis();
}
}
triggered = false;
System.out.println("some task here");
}
}
catch(InterruptedException ex) {
}
finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
PeriodicRunner pr = new PeriodicRunner();
new Thread(pr).start();
pr.trigger();
}
}