3

下面的类充当一个简单的缓存,它很少更新(例如,一天两次)并且被读取很多(最多每秒几次)。有两种不同的类型,aList和 a Map。我的问题是关于方法中数据更新后的新分配update。应用新数据的最佳(最安全)方式是什么?

我应该补充一点,读者没有必要看到绝对的最新值。要求只是在任何给定时间获得旧值或新值。

public class Foo {

    private ThreadPoolExecutor _executor;
    private List<Object> _listObjects = new ArrayList<Object>(0);
    private Map<Integer, Object> _mapObjects = new HashMap<Integer, Object>();
    private Object _mutex = new Object();
    private boolean _updateInProgress;

    public void update() {

        synchronized (_mutex) {
            if (_updateInProgress) {
                return;
            } else {
                _updateInProgress = true;
            }
        }

        _executor.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    List<Object> newObjects = loadListObjectsFromDatabase();
                    Map<Integer, Object> newMapObjects = loadMapObjectsFromDatabase();

                    /*
                     * this is the interesting part
                     */
                    _listObjects = newObjects;
                    _mapObjects = newMapObjects;

                } catch (final Exception ex) {
                    // error handling
                } finally {
                    synchronized (_mutex) {
                        _updateInProgress = false;
                    }
                }
            }
        });
    }

    public Object getObjectById(Integer id) {
        return _mapObjects.get(id);
    }

    public List<Object> getListObjects() {
        return new ArrayList<Object>(_listObjects);
    }


}

如您所见,目前没有使用ConcurrentHashMapCopyOnWriteArrayList使用。唯一的同步是在更新方法中完成的。

尽管对于我当前的问题不是必需的,但对于读者必须始终获得绝对最新价值的情况,了解最佳解决方案也很棒。

4

2 回答 2

1

您可以使用计划同步,除非您每秒读取超过 10,000 次。

如果你想要并发访问,我会使用 ConcurrentHashMap 或 CopyOnWriteArrayList 等并发集合。这些比同步集合更易于使用。(即出于性能原因您不需要它们,为简单起见使用它们)

顺便说一句:现代 CPU 可以在 0.1 秒内执行数十亿次操作,因此每秒几次对于计算机来说是永恒的。

于 2012-06-19T10:34:13.707 回答
0

我也看到了这个问题并想到了多种解决方案:

  1. 在两个代码上使用同步块,一个在读,另一个在写。
  2. 制作一个单独的删除列表,在该列表中添加所有可移动项目。在读取完成后读取列表的同一线程中删除。这样读取和删除将按顺序进行,不会出现错误。
于 2012-09-12T12:57:18.630 回答