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

时间:2017-02-28 08:34:34

标签: java multithreading

我需要一个系统来超时(继续代码),如果它在一段时间内没有停止,可以稍后重置。

我的问题是,当我同步到Map时,它允许我检查是否存在密钥,但是当我完成并清理时,线程已经检查它是否已被清除。当然,如果其中任何一个有意义,那就意味着线程认为我没有清理它。

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

我对多线程非常陌生,并希望有任何事情可以指向正确的方向(阅读的内容可以帮助解决这个问题)。我不知道从哪里开始或任何可以实现这一目标。

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

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.
}

1 个答案:

答案 0 :(得分:1)

简单的地图不适合并发访问/同步。您至少需要synchronized mapConcurrentHashMap。但是对于测试和设置场景(例如“如果键不存在放置键/值”)仍然不够,因为只有单个操作(如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 Concurrency in Practice