Переменные Python знают свои типы в зависимости от типа назначенной им переменной. Это язык динамических типов. В вашем коде интерпретатор видит foo1 = foo1[0] = [0]
и в конце находит значение, равное [0]
. Это список с одним элементом 0
. Теперь это присваивается первому элементу списка foo1
- foo1[0] = [0]
. Но поскольку foo1
уже объявлено, он создает объект, который имеет указатель на себя, и, следовательно, foo1
получает самоссылку бесконечно, причем самый внутренний список имеет 0.
Структура списка foo1
будет таким же, когда код foo1 = foo1[0]
.
Объект foo1
вошел в бесконечный цикл с собственной ссылкой.
Что ж, вариантов действительно не так уж и много. Позвольте мне пройти через перечисленные в подклассы :
DelayQueue
, LinkedBlockingDeque
, PriorityBlockingQueue
и SynchronousQueue
созданы для особые случаи, требующие дополнительной функциональности; они не имеют смысла в этом сценарии.
Остается только ArrayBlockingQueue
и LinkedBlockingQueue
. Если вы знаете, как определить, нужен ли вам ArrayList
или LinkedList
, вы, вероятно, сможете сами ответить на этот вопрос.
Обратите внимание, что в LinkedBlockingQueue
, " связанные узлы динамически создаются при каждой вставке "; это может подтолкнуть вас к ArrayBlockingQueue
.
SynchronousQueue
созданы для особых случаев, требующих дополнительных функций; они не имеют смысла в этом сценарии.
Остается только ArrayBlockingQueue
и LinkedBlockingQueue
. Если вы знаете, как определить, нужен ли вам ArrayList
или LinkedList
, вы, вероятно, сможете сами ответить на этот вопрос.
Обратите внимание, что в LinkedBlockingQueue
, " связанные узлы динамически создаются при каждой вставке "; это может подтолкнуть вас к ArrayBlockingQueue
.
SynchronousQueue
созданы для особых случаев, требующих дополнительных функций; они не имеют смысла в этом сценарии.
Остается только ArrayBlockingQueue
и LinkedBlockingQueue
. Если вы знаете, как определить, нужен ли вам ArrayList
или LinkedList
, вы, вероятно, сможете сами ответить на этот вопрос.
Обратите внимание, что в LinkedBlockingQueue
, " связанные узлы динамически создаются при каждой вставке "; это может подтолкнуть вас к ArrayBlockingQueue
.
ArrayList
или LinkedList
, вы, вероятно, сможете сами ответить на этот вопрос.
Обратите внимание, что в LinkedBlockingQueue
, " связанные узлы динамически создаются при каждой вставке "; это может подтолкнуть вас к ArrayBlockingQueue
.
ArrayList
или LinkedList
, вы, вероятно, сможете сами ответить на этот вопрос.
Обратите внимание, что в LinkedBlockingQueue
, " связанные узлы динамически создаются при каждой вставке "; это может подтолкнуть вас к ArrayBlockingQueue
.
Вы можете написать систему, чувствительную к задержке, на Java, но вы должны быть осторожны с распределением памяти, передачей информации между потоками и блокировкой. Вам следует написать несколько простых тестов, чтобы узнать, сколько времени эти вещи стоят на вашем сервере. (Они различаются в зависимости от ОС и архитектуры памяти)
Если вы сделаете это, вы сможете получить стабильные тайминги для операций до 99,99% времени. Это не настоящий режим реального времени, но может быть достаточно близким. В торговой системе стоимость использования Java вместо C может стоить 100 фунтов в день, однако стоимость разработки на C / C ++, а не на Java, вероятно, будет намного выше. например, с точки зрения гибкости, которую он дает нам, и количества ошибок, которые он сохраняет.
Вы можете получить довольно много джиттера, который вы бы наблюдали в программе на C, выполняющей то же самое. Некоторые называют это "C-подобной" Java.
К сожалению, для передачи объекта между потоками в Java через ArrayBlockingQueue на серверах, над которыми я работаю, требуется около 8 микросекунд, и я предлагаю вам проверить это на своих серверах. Простой тест - передать System.nanoTime () между потоками и посмотреть, сколько времени это займет.
ArrayBlockingQueue имеет «особенность», при которой он создает объект для каждого добавленного элемента (хотя для этого нет особых причин так и сделай) Так что, если вы найдете стандартную реализацию, которая этого не делает, дайте мне знать.
LinkedBlockingQueue
будет иметь стоимость вставки O (1), если не будет задержки выделения памяти. Очень большой ArrayBlockingQueue
будет иметь стоимость вставки O (1), если система не заблокирована из-за сборки мусора; однако при заполнении он будет блокироваться при вставке.
Даже с одновременной сборкой мусора я не уверен, следует ли вам писать систему реального времени на управляемом языке.
Я согласен с замечанием Эндрю Даффи о том, что реализация такой системы с ограничениями по времени в java может быть ошибкой. В любом случае, предполагая, что вы состоите в браке с JVM и не ожидаете, что эта очередь будет заполнена (т. Е. Потребитель может справиться с нагрузкой), я думаю, вам лучше всего подойдет пользовательская реализация, подобная ArrayBlockingQueue но урезан / оптимизирован для сценария одного производителя / потребителя. В частности, мне нравится идея вращения на стороне производителя для ожидания свободного места, а не блокировки.
Я обратился к источникам java.concurrent за руководством и составил проект этого алгоритма. ...
Мне это кажется неплохим, но он полностью не тестировался и, возможно, не быстрее на практике (возможно, не революционный, но я сам проверял :-). В любом случае, мне это понравилось ... Можете ли вы найти недостаток?
Псевдокод:
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final E[] buffer;
private int head = 0
private int tail = 0;
public void put(E e) {
if (e == null) throw NullPointerException();
while (buffer[tail] != null) {
// spin, wait for space... hurry up, consumer!
// open Q: would a tight/empty loop be superior here?
Thread.sleep(1);
}
buffer[tail] = e;
tail = (tail + 1) % buffer.length;
if (count.getAndIncrement() == 0) {
sync(takeLock) { // this is pseudocode -- should be lock/try/finally/unlock
notEmpty.signal();
}
}
}
public E take() {
sync(takeLock) {
while (count.get() == 0) notEmpty.await();
}
E item = buffer[head];
buffer[head] = null;
count.decrement();
head = (head + 1) % buffer.length;
return item;
}
ArrayBlockingQueue, вероятно, будет быстрее, поскольку вам не нужно создавать узлы ссылок при вставке. Обратите внимание, однако, что ArrayBlockingQueue имеет фиксированную длину, если вы хотите, чтобы ваша очередь увеличивалась произвольно (по крайней мере до Integer.MAX_INT), вам придется использовать LinkedBlockingQueue (если вы не хотите выделить массив элементов Integer.MAX_INT) .
Если требования к времени настолько жесткие, вам, вероятно, потребуется провести обширный тест на том же самом оборудовании, чтобы определить наиболее подходящее.
Если бы я угадал, я бы используйте ArrayBlockingQueue
, потому что коллекции на основе массивов, как правило, имеют удобную локальность ссылок.