1

我有一个 DAOClass,它从下面的许多线程中调用,用于插入一组表 -

public class DAOClass
{

private HashMap<String, HelperClass> insertBuffer;


public DAOClass() 
{
    insertBuffer = new HashMap<String, HelperClass>();      
}

public int[] createSomeTable(String key, SomeTableRecord someTableRecord) 
{
        List<SomeTableRecord> someTableRecList;
        HelperClass buf = insertBuffer.get(key);
        if (buf == null)
        {
            buf = new HelperClass();
            insertBuffer.put(key, buf);
        }

        someTableRecList = buf.getSomeTableBuffer();
        someTableRecList.add(someTableRecord);

        if(someTableRecList.size() >= Global.limit())
        {
            return flushSomeTableInsertCache(key);
        }
        else
        {
            return null;
        }
}

public int[] flushSomeTableInsertCache(String key)
{
    HelperClass buf = insertBuffer.get(key);
    int[] retVal = null;
    if (buf != null && buf.getSomeTableBuffer() != null)
    {
        retVal = createSomeTableBuffered(buf.getSomeTableBuffer());
        buf.getSomeTableBuffer().clear();
    }
    return retVal;
}

}

public int[] createSomeTableBuffered(final List<SomeTableRecord> someTableRecordList) 
{
  INSERT QUERY GOES HERE from LIST..
}
}

不同的线程调用 createSomeTable 方法,该方法添加到 HelperClass 的 ArrayList。有一个 HashMap 但键是重叠的,即多个线程同时命中同一个键,从而破坏 HashMap 和不合时宜的刷新..

助手类如下 -

class HelperClass {

private String key;
private ArrayList<SomeTableRecord> someTableBuffer;
private ArrayList<SomeTable1Record> someTable1Buffer;


HelperClass() {

    someTableBuffer = new ArrayList<SomeTableRecord>();
    someTable1Buffer = new ArrayList<SomeTable1Record>();

}

public ArrayList<SomeTableRecord> getSomeTableBuffer() {
    return someTableBuffer;
}

public ArrayList<SomeTable1Record> getSomeTable1Buffer() {
    return someTable1Buffer;
}
}

但是,这显然不是线程安全的,因为 key 不是不相交的。您能否建议在课程中进行一些更正,以便它是线程安全的。

4

6 回答 6

0

改用类 ConcurrentHashMap。

于 2013-02-20T10:08:05.257 回答
0

您应该使用而不是使用ArrayList<HelperClass>HashMap。为避免冲突,请使用

public synchronized int[] createSomeTable(String key, SomeTableRecord someTableRecord) 

保护你的缓冲区。

更新:

即使在 Spring 中也要保护缓冲区,还要synchronized添加flushSomeTableInsertCache

public synchronized int[] flushSomeTableInsertCache(String key)

实际上,您不仅仅使用keys 来识别元素。

否则,以这种方式观察键冲突不是一个好策略,因为它们甚至可能在 2 次刷新之间发生,所以你应该在数据库中检查它们,或者为键设置一个单独的 HashSet(如果你确定你拥有所有那里的钥匙)。

于 2013-02-20T10:13:55.017 回答
0

insertBuffer是这里唯一的状态。在多线程环境中修改其内容可能会导致意外行为。您可以同步对它的访问或使用ConcurrentHashMap而不是HashMap.

于 2013-02-20T10:16:01.640 回答
0

我会使用synchronized方法而不是ConcurrentHashMap. 但是,使用ConcurrentHashMap也可以解决您的线程安全问题。

于 2013-02-20T10:24:50.313 回答
0

分离用法的最简单方法是DAOClass为每个线程创建一个对象。

于 2013-02-20T10:25:16.140 回答
0

将您的实现更改为 ConcurrentHashMap,这将解决您的并发问题。

于 2013-02-20T12:24:59.827 回答