Синхронизация на Целочисленном значении [дубликат]

Я думаю, что вы ищете SUMIF и SUMIFS.

Если исходные данные указаны в Sheet1, попробуйте:

  1. Формула для ВСЕГО ВЕСА : =SUMIF(Sheet1!N:N,A2,Sheet1!K:K).

enter image description here

  1. Формула для МАТЕРИАЛ 1 : =SUMIFS(Sheet1!$A:$A,Sheet1!$N:$N,$A2,Sheet1!O:O,"X").

enter image description here

  1. Формула для МАТЕРИАЛ 2 : =SUMIFS(Sheet1!$A:$A,Sheet1!$N:$N,$A2,Sheet1!P:P,"X").

enter image description here

32
задан Community 23 May 2017 в 10:31
поделиться

9 ответов

Вы действительно не хотите синхронизироваться на Integer, так как Вы не управляете тем, какие экземпляры являются тем же и какие экземпляры отличаются. Java просто не предоставляет такую услугу (если Вы не используете Целые числа в маленьком диапазоне), который надежен через другой JVMs. Если действительно необходимо синхронизироваться на Целом числе, то необходимо сохранить Карту или Набор Целого числа, таким образом, можно гарантировать, что Вы получаете точный экземпляр, который Вы хотите.

Лучше должен был бы создать новый объект, возможно, хранивший в HashMap, который включается эти Integer, для синхронизации на. Что-то вроде этого:

public Page getPage(Integer id) {
  Page p = cache.get(id);
  if (p == null) {
    synchronized (getCacheSyncObject(id)) {
      p = getFromDataBase(id);
      cache.store(p);
    }
  }
}

private ConcurrentMap<Integer, Integer> locks = new ConcurrentHashMap<Integer, Integer>();

private Object getCacheSyncObject(final Integer id) {
  locks.putIfAbsent(id, id);
  return locks.get(id);
}

Для объяснения этого кода это использует ConcurrentMap, который позволяет использование putIfAbsent. Вы могли сделать это:

  locks.putIfAbsent(id, new Object());

, но тогда Вы несете (маленькие) расходы создания Объекта для каждого доступа. Избегать, чтобы, я просто сохранил само Целое число в Map. Чего это достигает? Почему это несколько отличается от просто использования самого Целого числа?

, Когда Вы делаете get() от Map, ключи по сравнению с [1 111] (или по крайней мере используемый метод является эквивалентом использования equals()). Два различных Целочисленных экземпляра того же значения будут равны друг другу. Таким образом можно передать любое количество различных Целочисленных экземпляров" new Integer(5)" как параметр к [1 114], и Вы будете всегда возвращать только самый первый экземпляр, который был передан в этом, содержал то значение.

существуют причины, почему Вы не можете хотеть синхронизироваться на [1 115]... можно войти в мертвые блокировки, если несколько потоков синхронизируются на [1 116] объекты и таким образом невольно используют те же блокировки, когда они хотят использовать различные блокировки. Можно зафиксировать этот риск при помощи

  locks.putIfAbsent(id, new Object());

версия и таким образом несение (очень) маленькой стоимости для каждого доступа к кэшу. Делая это, Вы гарантируете, что этот класс будет делать свою синхронизацию на объекте, на котором не будет синхронизироваться никакой другой класс. Всегда Хорошая Вещь.

50
ответ дан 27 November 2019 в 20:27
поделиться

Integer.valueOf() только возвраты кэшировали экземпляры для ограниченного диапазона. Вы не определили свой диапазон, но в целом, это не будет работать.

Однако я настоятельно рекомендовал бы не проявить этот подход, даже если значения находятся в корректном диапазоне. Начиная с этих кэшируемых Integer экземпляры доступны любому коду, Вы не можете полностью управлять синхронизацией, которая могла привести к мертвой блокировке. Это - те же трудные люди, имеют попытку соединить результат String.intern().

лучшая блокировка является частной переменной. Так как только Ваш код может сослаться на него, можно гарантировать, что никакие мертвые блокировки не произойдут.

Между прочим, с помощью WeakHashMap не будет работать также. Если экземпляр, служащий ключом, будет не имеющим ссылки, то он будет собран "мусор". И если на это сильно ссылаются, Вы могли бы использовать его непосредственно.

4
ответ дан 27 November 2019 в 20:27
поделиться

Используйте ориентированную на многопотоковое исполнение карту, такой как ConcurrentHashMap. Это позволит Вам управлять картой безопасно, но использовать другую блокировку, чтобы сделать реальное вычисление. Таким образом у Вас могут быть множественные вычисления, работающие одновременный с единственной картой.

Использование ConcurrentMap.putIfAbsent, но вместо того, чтобы поместить фактическое значение, использование Future с в вычислительном отношении легкой конструкцией вместо этого. Возможно FutureTask реализация. Выполните вычисление и затем get результат, который ориентировано на многопотоковое исполнение заблокируется, пока не сделано.

4
ответ дан 27 November 2019 в 20:27
поделиться

Используя синхронизируемый на Целом числе звучит действительно неправильным дизайном.

, Если необходимо синхронизировать каждый объект индивидуально только во время, получают/хранят Вас, может создать Набор и сохранить там в настоящее время блокируемые объекты. В другом слова

// this contains only those IDs that are currently locked, that is, this
// will contain only very few IDs most of the time
Set<Integer> activeIds = ...

Object retrieve(Integer id) {
    // acquire "lock" on item #id
    synchronized(activeIds) {
        while(activeIds.contains(id)) {
            try { 
                activeIds.wait();   
            } catch(InterruptedExcption e){...}
        }
        activeIds.add(id);
    }
    try {

        // do the retrieve here...

        return value;

    } finally {
        // release lock on item #id
        synchronized(activeIds) { 
            activeIds.remove(id); 
            activeIds.notifyAll(); 
        }   
    }   
}

то же переходит к хранилищу.

нижняя строка: нет никакой одной строки кода, который решает эту проблему точно способ, которым Вам нужно.

3
ответ дан 27 November 2019 в 20:27
поделиться

Как насчет ConcurrentHashMap с Целым числом возражает как ключи?

1
ответ дан 27 November 2019 в 20:27
поделиться

Вы могли взглянуть на этот код для создания взаимного исключения из идентификатора. Код был написан для Идентификаторов строки, но мог легко быть отредактирован для Целочисленных объектов.

1
ответ дан 27 November 2019 в 20:27
поделиться

Как Вы видите от множества ответов, существуют различные способы освежевать эту кошку:

  • Goetz и подход al хранения кэша FutureTasks работают вполне хорошо в таких ситуациях, где Вы "кэшируете что-то так или иначе", так не возражайте создавать карту объектов FutureTask (и если Вы действительно возражали против роста карты, по крайней мере, легко сделать сокращение его параллельным)
  • Как общий ответ на, "как соединить идентификатор", подход, обрисованный в общих чертах Antonio, имеет преимущество, что очевидно, когда карта блокировок добавляется к от.

Вы, возможно, должны не упустить потенциальную проблему с Antonio реализация , а именно, что notifyAll () разбудит потоки, ожидающие на весь идентификаторы, когда один из них станет доступным, который не может масштабироваться очень хорошо в соответствии с высокой конкуренцией. В принципе я думаю, что можно зафиксировать это при наличии объекта Условия для каждого в настоящее время блокируемого идентификатора, который является тогда вещью, которой Вы ждете/сигнализируете. Конечно, если на практике редко существует больше чем один идентификатор, ожидающий на в любой момент времени, то это не проблема.

1
ответ дан 27 November 2019 в 20:27
поделиться

Steve,

Ваш предложенный код имеет набор проблем с синхронизацией. (Antonio делает также).

Для суммирования:

  1. необходимо кэшировать дорогой объект.
  2. необходимо удостовериться, что, в то время как один поток делает извлечение, другой поток также не пытается получить тот же объект.
  3. , Что для n-потоков вся попытка получить объект только 1 объект когда-либо получается и возвращается.
  4. , Что для потоков, запрашивающих различные объекты, что они не спорят друг с другом.

псевдо код, чтобы заставить это произойти (использование ConcurrentHashMap как кэш):

ConcurrentMap<Integer, java.util.concurrent.Future<Page>> cache = new ConcurrentHashMap<Integer, java.util.concurrent.Future<Page>>;

public Page getPage(Integer id) {
    Future<Page> myFuture = new Future<Page>();
    cache.putIfAbsent(id, myFuture);
    Future<Page> actualFuture = cache.get(id);
    if ( actualFuture == myFuture ) {
        // I am the first w00t!
        Page page = getFromDataBase(id);
        myFuture.set(page);
    }
    return actualFuture.get();
}

Примечание:

  1. java.util.concurrent. Будущее является интерфейсом
  2. java.util.concurrent. Будущее на самом деле не имеет набора (), но смотрит на существующие классы, которые реализуют будущее, чтобы понять, как реализовать Ваше собственное будущее (Или использовать FutureTask)
  3. , Продвижение фактического извлечения к рабочему потоку почти наверняка будет хорошей идеей.
1
ответ дан 27 November 2019 в 20:27
поделиться

Посмотрите раздел 5.6 в Параллелизм Java на практике : "Создавая эффективный, масштабируемый, кэш результата". Это занимается точной проблемой, которую Вы пытаетесь решить. В частности, проверьте memoizer шаблон.

alt text
(источник: umd.edu )

1
ответ дан 27 November 2019 в 20:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: