使用线程监视HashMap更新

时间:2014-07-02 15:14:14

标签: java multithreading concurrency executorservice

使用Java线程监控Java数据结构中的更新的最佳方法是什么?我将通过实现Runnable接口来创建一个线程。该线程需要每10分钟睡眠和唤醒,并检查HashMap是否更新。在Java中执行此操作的最佳方法是什么? 任何帮助,非常感谢

5 个答案:

答案 0 :(得分:1)

好像你想让TimerTask检查地图是否每10分钟更新一次。

private Map map = new HashMap();
private Map lastMapState = new HashMap(map);
private boolean updated = false;

//....

private void startCheckingUpdates() {

    // Timers run their tasks in a separate Thread
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
        checkUpdated();
        }
    }, 600_000, 600_000);
}

//....

private boolean checkUpdated() {
    updated = !map.equals(lastMapState);
    lastMapState.clear();
    lastMapState.putAll(map);
    return updated;
}

答案 1 :(得分:0)

创建一个类来包装您的数据结构,当修改操作通过您的包装器更新lastModified字段时。当您的线程醒来时,只需检查lastModified字段以查看是否需要执行某些操作。

类似的东西:

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ModTimeMap<K, V> extends HashMap<K, V> {

    private Date lastModified;

    public Date getLastModified() {
        return lastModified;
    }

    @Override
    public void clear() {
        updateLastModified();
        super.clear();
    }

    @Override
    public V put(K arg0, V arg1) {
        updateLastModified();
        return super.put(arg0, arg1);
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> arg0) {
        updateLastModified();
        super.putAll(arg0);
    }

    @Override
    public V remove(Object arg0) {
        updateLastModified();
        return super.remove(arg0);
    }

    private void updateLastModified() {
        lastModified = new Date();// now
    }

}

我建议公开一些构造函数并添加一个序列版本ID,但这会让你有机会尝试。

答案 2 :(得分:0)

使用默认的HashMap实现,这不是一件容易的事情:您必须像上次查看的那样保留HashMap的副本,然后在最后看到的状态之间进行深入比较和目前的状态。进一步增加问题的方法是,该方法不会捕获地图发生变化的情况,然后在线程醒来之前进行更改。

我要做的是将HashMap子类化并添加getLastModified方法。覆盖每个修饰符方法(putremove等)并设置lastModified时间,然后调用super实现。然后,您的主题可以简单地检查新ChangeTrackingHashMap的修改时间,以查看自上次检查后它是否已更改。

答案 3 :(得分:0)

最好的方法是彻底改变这个概念。您实际上想要定期轮询您的地图。但是,您如何检测地图已更改?比较什么?有尺寸吗?但如果删除了一个条目而添加了其他条目,那么map的大小不会改变。

可能你想比较你在上一次迭代中创建的地图的克隆?但首先,地图可能非常大(例如,可以说有1亿个条目)。您必须迭代第一个映射以确保所有条目都在第二个映射中,然后迭代第二个映射以检查所有键是否在第一个映射中。否则你会错过额外的参赛作品。

我建议什么&gt;?我建议使用包装器来包装任何地图,该包装器调用常规地图的所有方法,除了一个:put()。此方法调用您的真实地图的放置,但也会创建特定条目更改的事件。在这种情况下,您将实时获得更改通知,而不是10分钟。

公共类NotifyableMap实现Map {      私人决赛地图;      public NotifyableMap(Map map)} {this.map = map;}

 public V put(K key, V value) {
     V oldValue = map.put(key, value);
     if (!value.equals(oldValue)) { // TODO: make this check null-safe
         // notify listeners here
     }
 }

 // all other methods are trivial 

}

答案 4 :(得分:0)

尝试:

ScheduledExecutorService daemon = Executors.newScheduledThreadPool(1);
daemon.scheduleWithFixedDelay(new MyRunnable(myMapToCheck), 
                              10, 10, TimeUnit.MINUTE);
//...
private static class MyRunnable implements Runnable {
    private final Map<K, V> lastState;
    private final Map<K, V> map;

    public MyRunnable(Map<K, V> map) {
        this.map = map;
        this.lastState = new HashMap<>(map);
    }

    @Override
    public void run() {
        // copy to avoid changes before updating lastState
        Map<K, V> currentState = new HashMap<>(map);
        if(currentState.equals(lastState)) {
            System.our.println("No change");
        } else {
            System.our.println("Change!");
        }
        lastState.clear();
        lastState.putAll(currentState);
    }
}