我需要一个系统来超时(继续代码),如果它在一段时间内没有停止,可以稍后重置。
我的问题是,当我同步到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.
}
答案 0 :(得分:1)
简单的地图不适合并发访问/同步。您至少需要synchronized map或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
。