繁体   English   中英

使用 Executors 时的空 Map

[英]Empty Map when using Executors

我试图在给定的时间范围内计算每分钟与List参数相同type的记录。 使用以下方法:

public Map<String, Object> getCountPerMinuteForType(final String type,
                                 final long startTimestamp,
                                 final long endTimestamp) {
    final Map<String, Object> countsPerMinForType = new HashMap<>();
    Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            int counter = 0;
            List<Data> dataList = storage.retrieveData();
            for(Data data: dataList){
                if (data.getType().equals(type) &&
                    data.getUnixTimestamp() >= startTimestamp &&
                    data.getUnixTimestamp() <= endTimestamp){
                    counter++;
                }
            }
            countsPerMinForType.put(type, counter);
        }, 0, 1, TimeUnit.MINUTES);
    return countsPerMinForType;
}

问题是,这个方法返回一个空的Map

当我在Executors打印Map的内容时,我可以看到它有数据。

这是因为另一个线程正在 Map 中执行放置操作。 主线程开始执行线程,然后返回到调用它的地方。 要解决此问题,您可能需要创建一个侦听器接口,每当第二个线程执行任务时都会调用该接口。

下面是代码示例,您可以根据需要使用和修改。

class Test implements Listener {
    private Listener listener;

    public Test() {
        listener = this; //Set this class as your listener
    }

    //Make your function return nothing
    public void getCountPerMinuteForType(final String type, final long startTimestamp, 
    final long endTimestamp) {

    final Map<String, Object> countsPerMinForType = new HashMap<>();
    ScheduledExecutorService service = 
    Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
        int counter = 0;
        List<Data> dataList = storage.retrieveData();
        for (Data data : dataList) {
            if (data.getType().equals(type) &&
                    data.getUnixTimestamp() >= startTimestamp &&
                    data.getUnixTimestamp() <= endTimestamp) {
                counter++;

            }
        }
        listener.onNewData(type, counter);
        countsPerMinForType.put(type, counter);
        }, 0, 1, TimeUnit.MINUTES);
        //return countsPerMinForType;
        //If service is terminated call the listener and perform your operation there
        if (service.isTerminated()) {
            listener.dataFilled(countsPerMinForType);
        }

    }

    @Override
    public void onNewData(String str, Object obj) {
        //Perform your task here
    }
    @Override
    public void dataFilled(Map<String, Object> data) {
        //Perform your task here
    }
}

interface Listener {
    void dataFilled(Map<String, Object> data);
    void onNewData(Map<String, Object> data);
}

您遇到的问题是,您期望正在分拆的线程已完成工作,并返回countsPerMinForType中填充的结果。 这不是正在发生的事情......

正在发生的事情是:

  1. 您从主/当前执行线程调用该方法
  2. Map已创建
  3. 一个新线程被分拆来做一些工作
  4. 几乎立即,该方法返回并且地图仍然是空的。 ...
  5. 方法完成后,被分离的线程正在执行的工作将被执行......随后调用方法永远不会看到结果。

您可以确认这是一个测试返回时timestamp的时候getCountPerMinuteForType开始和结束,而另一个timestamp为当Thread开始和结束。 开始时间将按顺序排列,结束时间将不按顺序排列。

此外,您可能需要考虑将ConcurrentHashMap用于多线程应用程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM