Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用线程监视HashMap更新_Java_Multithreading_Concurrency_Executorservice - Fatal编程技术网

Java 使用线程监视HashMap更新

Java 使用线程监视HashMap更新,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,使用Java线程监视Java数据结构中的更新的最佳方法是什么?我将通过实现一个可运行的接口来创建一个线程。该线程需要每10分钟睡眠和醒来一次,并检查HashMap是否更新。在Java中实现这一点的最佳方法是什么? 当修改操作通过包装器更新lastModified字段时,非常感谢您的帮助,请创建一个类来包装您的数据结构。当线程唤醒时,只需检查lastModified字段,查看是否需要执行某些操作 大概是这样的: import java.util.Date; import java.util.Has

使用Java线程监视Java数据结构中的更新的最佳方法是什么?我将通过实现一个可运行的接口来创建一个线程。该线程需要每10分钟睡眠和醒来一次,并检查HashMap是否更新。在Java中实现这一点的最佳方法是什么?
当修改操作通过包装器更新
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
    }

}
import java.util.Date;
导入java.util.HashMap;
导入java.util.Map;
公共类ModTimeMap扩展了HashMap{
上次修改的私人日期;
公共日期getLastModified(){
返回最后修改;
}
@凌驾
公共空间清除(){
updateLastModified();
super.clear();
}
@凌驾
公共V put(K arg0,V arg1){
updateLastModified();
返回super.put(arg0,arg1);
}
@凌驾

公屋空置(Map使用默认的HashMap实现这并不容易:您必须在线程上次看到HashMap时保留一份副本,然后在上次看到的状态和当前状态之间进行深入比较。进一步增加问题的是,该方法无法捕捉到映射更改然后在线醒了


我要做的是子类HashMap并添加一个
getLastModified
方法。重写每个修饰符方法(
put
remove
,等等)设置上次修改的时间,然后调用
super
实现。然后,线程只需检查新
ChangeTrackingHashMap
的修改时间,查看它自上次检查以来是否已更改。

最好的方法是完全更改概念。实际上,您希望对但是您想如何检测地图是否已更改?与什么进行比较?与大小进行比较?但是,如果一个条目已删除,而另一个条目已添加,则大小不会因地图更改而更改

可能您想将其与上一次迭代中创建的映射克隆进行比较?但首先,映射可能非常大(例如,1亿个条目)。您必须迭代第一个映射以确保所有项都在第二个映射中,然后迭代第二个映射以检查所有键都在第一个映射中。否则,您将丢失额外的项

我建议>?我建议使用调用常规映射的所有方法的包装器包装任何映射,除了一个:
put()
。此方法调用真实映射的put,但也会创建特定条目发生更改的事件。在这种情况下,您将实时收到更改通知,而不是在10分钟内

公共类NotifyableMap实现映射{ 私人最终地图; 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 
}试试:

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);
    }
}
ScheduledExecutorService守护进程=执行者。newScheduledThreadPool(1);
daemon.scheduleWithFixedDelay(新的MyRunnable(myMapToCheck)),
10,10,时间单位(分钟);
//...
私有静态类MyRunnable实现Runnable{
国家私人最终地图;
私人最终地图;
公共MyRunnable(地图){
this.map=map;
this.lastState=新HashMap(map);
}
@凌驾
公开募捐{
//在更新lastState之前复制以避免更改
Map currentState=新的HashMap(Map);
if(currentState.equals(lastState)){
System.our.println(“无变更”);
}否则{
System.our.println(“Change!”);
}
lastState.clear();
lastState.putAll(当前状态);
}
}

似乎您需要一个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;
}

这看起来像一个听起来有点格格不入的东西,也许你可以考虑当地图被更新时,哈希图中的一个包装类,它会触发一个改变事件。然后,任何可能为这个事件监听的东西都可以做出相应的反应。HashMap(或ConcurrentHashmap)每隔一段时间就会更新一次。我希望能够创建一个线程,该线程每10分钟唤醒一次,检查HashMap是否有新条目。他仍然必须
同步
对该映射的访问。写入不能保证在读取之前发生。哦,让我更清楚一点。HashMap是一个单例,因此它不是一个单例新对象是的,如果你想保证线程安全,每个方法都必须同步。如果这是一个问题,我绝对建议你从ConcurrentHashMap中进行子类化。@Dan Smith如果你不能更改正在使用的映射,那么你必须跟踪它的使用,在这个范例中。更难。@DanSmith-使它
Singleton
不会从
同步角度更改任何内容。如何保证所做的更改(添加的元素)在此线程中可见?这将如何确保之前发生?