并发和日历类 [英] Concurrency and Calendar classes

查看:105
本文介绍了并发和日历类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程(类实现runnable,称为AnalyzeTree)组织在一个哈希映射(ConcurrentMap> slicesMap)。类通过大型文本文件中的数据(这里称为树),并将地理坐标从其解析到HashMap。想法是一次处理一个树,并根据键添加或增加值(这只是一个表示时间的Double值)。

I have a thread (class implementing runnable, called AnalyzeTree) organised around a hash map (ConcurrentMap> slicesMap). The class goes through the data (called trees here) in the large text file and parses the geographical coordinates from it to the HashMap. The idea is to process one tree at a time and add or grow the values according to the key (which is just a Double value representing time).

代码的相关部分如下所示:

The relevant part of code looks like this:

// grow map entry if key exists
if (slicesMap.containsKey(sliceTime)) {

    double[] imputedLocation = imputeValue(
        location, parentLocation, sliceHeight,
        nodeHeight, parentHeight, rate,
        useTrueNoise, currentTreeNormalization,
        precisionArray);

    slicesMap.get(sliceTime).add(new Coordinates(imputedLocation[1], imputedLocation[0], 0.0));

    // start new entry if no such key in the map
} else {

    List<Coordinates> coords = new ArrayList<Coordinates>();

    double[] imputedLocation = imputeValue(
        location, parentLocation, sliceHeight,
        nodeHeight, parentHeight, rate,
        useTrueNoise, currentTreeNormalization,
        precisionArray);

    coords.add(new Coordinates(imputedLocation[1], imputedLocation[0], 0.0));

    slicesMap.putIfAbsent(sliceTime, coords);
    // slicesMap.put(sliceTime, coords);

}// END: key check

这个(执行者是ExecutorService executor = Executors.newFixedThreadPool(NTHREDS)):

And the class is called like this (executor is ExecutorService executor = Executors.newFixedThreadPool(NTHREDS) ):

mrsd = new SpreadDate(mrsdString);
int readTrees = 1;
while (treesImporter.hasTree()) {

    currentTree = (RootedTree) treesImporter.importNextTree();

    executor.submit(new AnalyzeTree(currentTree,
        precisionString, coordinatesName, rateString,
        numberOfIntervals, treeRootHeight, timescaler,
        mrsd, slicesMap, useTrueNoise));

    // new AnalyzeTree(currentTree, precisionString,
    // coordinatesName, rateString, numberOfIntervals,
    // treeRootHeight, timescaler, mrsd, slicesMap,
    // useTrueNoise).run();

    readTrees++;

}// END: while has trees

麻烦当并行执行(注释部分顺序运行良好),我认为它可能会抛出ConcurrentModificationException,但显然问题是在mrsd(SpreadDate对象的实例,这只是一个类的日期相关的计算)。

Now this is running into troubles when executed in parallel (the commented part running sequentially is fine), I thought it might throw a ConcurrentModificationException, but apparently the problem is in mrsd (instance of SpreadDate object, which is simply a class for date related calculations).

SpreadDate类如下所示:

The SpreadDate class looks like this:

public class SpreadDate {

    private Calendar cal;
    private SimpleDateFormat formatter;
    private Date stringdate;

    public SpreadDate(String date) throws ParseException {

        // if no era specified assume current era
        String line[] = date.split(" ");
        if (line.length == 1) {
            StringBuilder properDateStringBuilder = new StringBuilder();
            date = properDateStringBuilder.append(date).append(" AD").toString();
        }

        formatter = new SimpleDateFormat("yyyy-MM-dd G", Locale.US);
        stringdate = formatter.parse(date);

        cal = Calendar.getInstance();
    }

    public long plus(int days) {
        cal.setTime(stringdate);
        cal.add(Calendar.DATE, days);
        return cal.getTimeInMillis();
    }// END: plus

    public long minus(int days) {
        cal.setTime(stringdate);
        cal.add(Calendar.DATE, -days); //line 39
        return cal.getTimeInMillis();
    }// END: minus

    public long getTime() {
        cal.setTime(stringdate);
        return cal.getTimeInMillis();
    }// END: getDate
}

异常被抛出:

java.lang.ArrayIndexOutOfBoundsException: 58
at     sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:454)
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2098)
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2013)
at java.util.Calendar.setTimeInMillis(Calendar.java:1126)
at java.util.GregorianCalendar.add(GregorianCalendar.java:1020)
at utils.SpreadDate.minus(SpreadDate.java:39)
at templates.AnalyzeTree.run(AnalyzeTree.java:88)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)

如果将初始化mrsd的零件移动到AnalyzeTree类,它运行没有任何问题 - 初始化类每次这个线程运行,因此我的关注。

If a move the part initializing mrsd to the AnalyzeTree class it runs without any problems - however it is not very memory efficient to initialize class each time this thread is running, hence my concerns. How can it be remedied?

推荐答案

日历和日期是可变类的两个示例。您似乎正在ExecutorService中共享它们,并且您看到的结果是意外的。我建议为每个线程创建一个SpreadDate对象的新实例。

Calendar and Date are two example of mutable classes. You seem to be sharing them across the ExecutorService and the results as you see are unexpected. I would suggest creating a new instance of the SpreadDate object for each thread.

这篇关于并发和日历类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆