Как обработать (почти) бесконечный список в Java?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как обработать (почти) бесконечный список в Java?

Сообщение Anonymous »

Я использую поставщика объектного хранилища, который не реализует рекурсивное удаление. Когда кто-то приходит и просит удалить ведро, мне приходится опустошать его вручную. По сути, у меня есть два метода, которые я могу вызвать:

Код: Выделить всё

ListObjectsResponse listObjects(ListObjectsRequest);
DeleteObjectResponse deleteObject(DeleteObjectRequest);
Примечание listObjects поддерживает разбивку по страницам через start + limit, при этом ответ возвращает следующий стартовый токен.
Я постоянно сталкиваюсь с проблемами при различных попытках когда ведро содержит почти бесконечное количество объектов
Например, при использовании ForkJoinTask/

Код: Выделить всё

RecursiveTask
, большинство примеров, похоже, используют концепцию сортировки слиянием, чтобы разбить список на более мелкие фрагменты. Лично я не могу прочитать весь список в памяти без сбоев
Поэтому я изменил пример ForkJoin на две задачи. Первая — это «листовая задача», которая выполняет фактическое удаление данного списка. Вторая задача — это рекурсивная задача, которая считывает конечный пакет объектов, а затем планирует две задачи: листовую задачу, которая удаляет список, и другую рекурсивную задачу, которая получает следующий пакет. Псевдокод:

Код: Выделить всё

DeleteRecursiveTask extends RecursiveAction {
private final String startToken;

...

protected void compute() {
ListObjectsResponse response = listObjects(ListObjectsRequest.withStartToken(this.startToken));
DeleteLeafTask task1 = new DeleteLeafTask(response.getObjects());
DeleteRecursiveTask task2 = new DeleteRecursiveTask(response.getNextStartToken())
invokeAll(task1, task2);
}
}
Надежда/идея заключалась в том, что это приведет к самоограничению. То есть, если конечные задачи занимают больше времени, рекурсивная задача будет стоять в очереди, ожидая завершения одной из конечных задач, прежде чем получить еще больше объектов.
Некоторое время это работает, но в конечном итоге происходит сбой с StackOverflowException. Это связано с тем, что (насколько я могу судить) характер ForkJoinPool, «крадущий работу», означает, что ignoreAll фактически может запускать задачу в том же потоке. Таким образом, новая копия DeleteRecursiveTask помещается в стек, и это повторяется. Поведение является недетерминированным, основанным на планировании и прочем, но, учитывая почти бесконечный список, это в основном происходит всегда.
Действительно, даже в примерах, которые люди приводят, это кажется возможным. Конечно, при сортировке слиянием вам понадобится список порядка 2^1024 (если 1024 — максимальный размер стека), чтобы его можно было избежать статистически.
Есть ли способ избежать чтобы рекурсия не происходила в одном и том же потоке, или иным образом избежать бесконечно растущего стека? Я не нашел способа запланировать ForkJoinTask без этой возможности.
Итак, теперь я думаю, что мне нужно переместить чтение за пределы ForkJoin и заставить его планировать задачи. Но я не уверен, как изящно удовлетворить все следующие требования:
  • Удаление корзины X может привести к потенциально миллионам подзадач, которые все должны быть выполнены до того, как основная операция завершается
  • Должен поддерживаться тайм-аут, который отменит все подзадачи, связанные с данной операцией удаления сегмента X
  • Она должна регулироваться/самостоятельно -ограничение в том смысле, что объект, поставляющий очередь и планирующий задачи, должен гарантировать, что он не опережает рабочие потоки, иначе он рискует разместить слишком много в памяти.
  • Могут быть параллельные удалить запросы сегмента, и все они должны использовать один и тот же пул потоков (приоритет был бы хорош, но не обязателен)
Можно ли это легко сделать с помощью доступных классов JDK?

Подробнее здесь: https://stackoverflow.com/questions/787 ... st-in-java
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»