Java TimerTask等待最后一个任务

时间:2017-09-19 18:07:34

标签: java multithreading timer timertask

考虑以下示例:

// Helper constructor
public Timer(final TimerTask action, final long interval)
{
    scheduleAtFixedRate(action, 0, interval);
}

... (different class)

private Timer myTimer;

public void start()
{
    myTimer = new Timer(new TimerTask(){
        @Override
        public void run()
        {
            doStuff(); <<----------------------------
        }                                           |
    }, 10);                                         |
}                                                   |
                                                    |
public void stop()                                  |
{                                                   |
    myTimer.cancel();                               |
    myTimer.purge();                                |
    doMoreStuff(); // << may not be called while doStuff is running!
}

doStuff()做了一些需要时间的事情。我必须等到doStuff已经完成,如果有任何正在运行之后我想继续使用doMoreStuff。

是否有任何(合法的)方法可以添加我可以在这里使用的waitUntilFinished方法,或者我应该将java.util.Timer类复制到我自己的方法并自己实现该方法? / p>

2 个答案:

答案 0 :(得分:0)

TimerTask应该是异步的。

您需要正确实现线程管理。 使用Executors或线程池来监视任务执行生命周期。

答案 1 :(得分:0)

您可以使用显式锁定来执行此操作。

任务需要为doStuff()获取锁定,并在无法获得锁定后退出,事实上,它永远不会再次尝试doSuff()

stop()方法将取消Timer并锁定。它将阻塞直到它获得锁定,因此如果doStuff()正在进行,它将不得不等待。一旦它具有锁定,它就会明确地禁用该任务,这样在释放锁定之后,剩余的任务运行将不再尝试doStuff()。

public class TimerStuff {

    private Timer myTimer;
    private Lock lock;
    private ScheduledTask scheduledTask;

    public void start() {
        lock = new ReentrantLock();
        myTimer = new Timer();
        scheduledTask = new ScheduledTask(lock);
        myTimer.schedule(scheduledTask, 0, interval);
    }

    public void stop() {
        myTimer.cancel(); // stop the scheduling
        lock.lock(); // if doStuff is busy, we'll block until it's finished, once we have the lock the task cannot doStuff()

        try {
            scheduledTask.disable(); // once we release the lock, the task won't attempt to run again
            doMoreStuff(); // we're certain doStuff() isn't running, and won't run after this
        } finally {
            lock.unlock();
        }

    }

    private void doMoreStuff() {
        //***
    }

}

class ScheduledTask extends TimerTask {
    private final Lock lock;
    private volatile boolean mayRun = true;

    public ScheduledTask(Lock lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        mayRun = mayRun && lock.tryLock();
        if (mayRun) {
            try {
                doStuff();
            } finally {
                lock.unlock();
            }
        }
    }

    public void disable() {
        this.mayRun = false;
    }

    private void doStuff() {
        // ... the stuff
    }


}