Параллелизм Java: блокировка effiency

Моя программа имеет 100 потоков.

Каждый поток делает это:

1) если arrayList пуст, добавьте элемент с определенными свойствами к нему

2) если arrayList не пуст, выполните итерации через элементы, найденные в arrayList, если найдено подходящий элемент (соответствие определенным свойствам), получите его и удалите arrayList

Проблема здесь состоит в том, что, в то время как один поток выполняет итерации через arrayList, другие 99 потоков ожидают блокировки на arrayList.

Что Вы предложили бы мне, если я хочу, чтобы все 100 потоков работали в незапертом условии? Таким образом, они все должны проделать работу?

Спасибо

6
задан Ravi Gupta 5 February 2010 в 06:39
поделиться

5 ответов

Вы смотрели на разделяемую и монопольную блокировку ? Вы можете использовать общую блокировку для списка, а затем иметь свойство «удалено» для элементов списка. Предикат, который вы используете для проверки элементов списка, должен был бы убедиться, что элемент не помечен как `` удаленный '' в дополнение к любым другим запросам, которые у вас есть - также из-за потенциальных конфликтов чтения-записи вам нужно будет заблокировать каждый элемент, когда вы траверс. Затем периодически получайте эксклюзивную блокировку в списке, чтобы выполнять удаление по-настоящему.

Блокировка чтения допускает высокий уровень параллелизма в списке. Эксклюзивные блокировки для каждого элемента списка не так хороши, но вам нужно заставить модель памяти обновлять ваш флаг «удалено» для каждого потока, поэтому нет никакого способа обойти это.

2
ответ дан 17 December 2019 в 04:46
поделиться

Во-первых, если вы не работаете на машине с 64 или более ядрами, ваши 100 потоков, вероятно, сами по себе снижают производительность.

Тогда ArrayList для того, что вы описываете, определенно не лучший выбор, потому что удаление элемента не выполняется за амортизированное постоянное время, а за линейное время O (n).Так что это второй боров в производительности. Вероятно, вы захотите использовать LinkedList вместо ArrayList (если вы настаиваете на использовании списка).

Конечно, я очень сомневаюсь, что вам нужно перебирать полный список каждый раз, когда вам нужно найти один элемент: не будет ли другая структура данных более подходящей? Может быть, элементы, которые вы помещаете в свой список, имеют такое понятие, как «равенство», и, следовательно, вместо него можно использовать карту со временем поиска O (1)?

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

2
ответ дан 17 December 2019 в 04:46
поделиться

Если ваше понятие «подходящий элемент (соответствующий определенным свойствам)» можно закодировать с помощью Comparator , тогда PriorityBlockingQueue позволит каждому потоку опросить очередь, взяв следующий элемент без необходимости поиска в списке или постановки нового элемента в очередь, если очередь пуста.

Приложение: Тило поднимает важный вопрос: по мере развития вашего подхода вы можете захотеть эмпирически определить, сколько потоков является оптимальным.

1
ответ дан 17 December 2019 в 04:46
поделиться

Предполагая, что вы используете RadioSelect в качестве виджета для forms.ChoiceField , вы можете сделать что-то вроде:

choices = (('1', 'First help_text here'),
           ('2', 'Second help_text here'),
           ('3', 'Third help_text here'),
          )

class MyForm(forms.Form):
    ...
    choice = forms.ChoiceField(widget = RadioSelect, choices = choices)

Это не строгое использование help _ text , но это должно быть сделано в большинстве случаев.

-121--3713280-

Я думаю, что использовать файлы жесткого диска для хранения данных - лучший выбор

-121--3545577-

Ключ заключается в использовании блокировки объекта в списке массивов только в том случае, если это действительно необходимо.

Хорошей идеей было бы объединение списка массивов подклассов и обеспечение синхронизации в одиночных процессах чтения + записи + удаления.

Это обеспечит тонкую детализацию с блокировкой, позволяя потокам проходить через массив перечислять одновременно защищая семантику списка массивов.

0
ответ дан 17 December 2019 в 04:46
поделиться

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

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

Например,

public class ReportParameterViewModel
{
    public DateTime OrderRangeBegin { get; set; }
    public DateTime OrderRangeEnd { get; set; }
    public string Department { get; set; }
    public int Customer_Number { get; set; }
    public double Commission_Rate { get; set; }
    public int Page_Start { get; set; }
    public int Page_End { get; set; }
    public bool IsExecutiveVersion { get; set; }
    //
    // ...and so on...
    //
}

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

-121--3018735-

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

-121--4196016-

Один поток владеет массивом и несет ответственность за его добавление и итерацию, чтобы найти нужную работу. После того как единица работы найдена, поместите ее в очередь. Пусть все рабочие потоки используют take () для удаления работы из очереди.

Это позволяет обнаруживать несколько единиц работы за один проход через массив и передавать их ожидающим рабочим потокам достаточно эффективно.

0
ответ дан 17 December 2019 в 04:46
поделиться