Код: Выделить всё
ListObjectsResponse listObjects(ListObjectsRequest);
DeleteObjectResponse deleteObject(DeleteObjectRequest);
Я постоянно сталкиваюсь с проблемами при различных попытках когда ведро содержит почти бесконечное количество объектов
Например, при использовании 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
- Она должна регулироваться/самостоятельно -ограничение в том смысле, что объект, поставляющий очередь и планирующий задачи, должен гарантировать, что он не опережает рабочие потоки, иначе он рискует разместить слишком много в памяти.
- Могут быть параллельные удалить запросы сегмента, и все они должны использовать один и тот же пул потоков (приоритет был бы хорош, но не обязателен)
Подробнее здесь: https://stackoverflow.com/questions/787 ... st-in-java
Мобильная версия