带有重复超时的线程(停止超时并在事件发生后稍后重置)



我需要一个系统才能超时(继续代码),如果暂时不停止,请以后重置。

我的问题是当我同步到地图时,它允许我检查是否存在钥匙,但是到我完成并清理所有内容时,线程已经检查了是否已清理。当然,如果有道理的话,这意味着线程认为我不会在我愿意的时候清理它。

这应该让我在检查之前暂停清理线程,然后重置超时并在完成后继续检查。

我是多线程的新手,希望任何东西都指向正确的方向(可以阅读以帮助此等)。我不知道从哪里开始或任何可以实现这一目标的东西。

代码示例(希望这是有道理的:))

TestLock lock = new TestLock();
//The lock would get stored with other data See Below: Foo data = map.get("foo");
new Thread()
{
    @Override
    public void run()
    {
        //Simply holds idle until the lock timesout.
        lock.waitForTimeout(TimeUnit.MILISECONDS, 500); //Timeout is half a second
        //Code can continue here if the lock hasn't got reset by the time it times out.
        //Timeout will not countdown while it's stopped. See Below: code.getTimeoutLock().stop();
        //Check if item is in map and cleanup
    }
}.start();
//Somewhere else in the main thread
Foo data = map.get("foo"); //Holds the lock for cleanup
if (data != null)
{
    //Stopping the lock can happen at any time to cancel timeout.
    data.getTimeoutLock().stop(); //Stop the lock timeout
    //Do my stuff
    //This is where the thread would check if I removed the data object.
    if (foo) //Random if that may or may not be true
    {
        map.remove("foo"); //Cleanup myself
    }
    data.getTimeoutLock().reset(); //Reset the lock timeout to what was set and continue timeout.
}

简单的映射不适合并发访问/同步。您至少需要同步地图或ConcurrentHashMap。但这仍然不足以用于测试和集合的方案(例如,"如果不存在键,则键/值"),因为只有单个操作(例如contains())是线程安全的。在contains()put()之间,另一个线程可能会访问地图并从contains()调用中无效。结果,您需要另一个锁。示例:

public class MapSample {
    private final Object lock = new Object();
    public void doSomething() {
        // Do not access/edit map except for simple read operations
        synchronized(lock) {
            // access/edit map…
        }
        // Do not access/edit map except for simple read operations
    }
}

但是,由于您等待某些事情发生,所以我认为CountDownLatch将是一个更明智的解决方案:

public class LatchSample {
    private final CountDownLatch latch = new CountDownLatch(1);
    public void doSomething() {
        // do something
        // signal completion after you did what you had to do
        latch.countDown();
    }
    public void doSomethingAfterCompletion() {
        // will block until countDown() is called
        latch.await();
    }
}

如果您必须重复等待,请使用CyclicBarrier

建议阅读:Java并发

最新更新