此问题类似于以下现有问题。我知道IndexOutOfBoundsException
是RuntimeException
,因此很明显代码中存在错误。
traversing a List<Future> object throws IndexOutOfBounds exception
在我的情况下,此异常实际发生在实际传输文件的API中。它会被call()(Lambda)捕获并被视为失败以进行重试。
java项目中有各种文件传输任务。因此,我使用ExecutorService
来满足要求。
有一个文件列表,每个文件将从这些文件提供给ExecutorService
,我传递 Callable ,如果传输失败,最终会返回文件对象。
我知道我一定做错了。
请建议需要做哪些更改,感谢您的时间。
如果需要任何其他信息,请告诉我。
(用虚拟名称替换真实的类和方法名称)
异常堆栈跟踪
java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at FileTransfer.lambda$transfer$1(FileTransfer.java)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at FileTransfer.transfer(FileTransfer.java)
Caused by: java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
at java.util.LinkedList.get(LinkedList.java:476)
at com.autofixrt.errorhandler.strategy.retry.FileTransfer.lambda$transfer$0(FileTransfer.java)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
以下是正在进行文件传输操作的java方法。
FileTransfer.java
public class FileTransfer {
public boolean transfer(List<File> fileList) {
final int size = fileList.size();
final int[] pos = {0};
// Also tried with AtomicInteger but gives the same IndexOutOfBoundsException
final ExecutorService executor = ExecutorUtil.createDefaultExecutor();
final List<Future<File>> futureList = new ArrayList<>();
try {
while (pos[0] < size) {
final Future<File> future = executor.submit(() -> {
File failed = null;
// Exception caused by at below line
// Caused by: java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
final File input = fileList.get(pos[0]++); // caused by
try {
final boolean isSuccess = // API call to transfer file;
if (!isSuccess)
failed = input;
} catch (final Exception e) {
failed = input;
}
return failed;
}); // submit ends
futureList.add(future);
} // while ends
final List<File> failedList = new ArrayList<>(0);
// iterate over list of futures collected above
futureList.forEach(f -> {
try {
// java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
final File input = f.get(); // Exception occures at this line
if (input != null)
failedList.add(input);
} catch (Exception e) {
System.out.println("Error in retrieving failed from future");
e.printStackTrace();
}
});
} finally {
ExecutorUtil.shutdown(executor);
futureList.clear();
}
boolean success = true;
// send failed email, if still failed present
if (!isEmpty(failed)) {
success = false;
// sendErrorEmail(failedList);
}
return success;
}
}
ExecutorUtil.java
public final class ExecutorUtil {
private ExecutorUtil() { }
private static final int DEFAULT_THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
public static ExecutorService createDefaultExecutor() {
return createExecutor(DEFAULT_THREAD_POOL_SIZE);
}
private static ExecutorService createExecutor(int threadPoolSize) {
return Executors.newFixedThreadPool(threadPoolSize);
}
public static void shutdown(ExecutorService executor) {
if (isNull(executor))
return;
executor.shutdown(); // Disable new tasks from being submitted
try {
// Wait 20 seconds for existing tasks to terminate
if (!executor.awaitTermination(20L, TimeUnit.SECONDS)) {
executor.shutdownNow(); // Cancel currently executing tasks
// Wait 10 seconds for tasks to respond to being cancelled
if (!executor.awaitTermination(10L, TimeUnit.SECONDS))
System.out.println("Pool did not terminate");
else
System.out.println("Thread pool has been shutdown");
} else
System.out.println("Thread pool has been shutdown - no await");
} catch (InterruptedException e) {
// (Re-)Cancel if current thread also interrupted
executor.shutdownNow();
}
}
}
答案 0 :(得分:-1)
int[0]
不是线程安全的。请改用AtomicInteger
。您的条件while (i < size)
在主线程上执行,而增量i++
在执行程序线程上完成。可能的执行是:
i = 0;
while (i < 1) //true
executor.submit(...)
//note that i hasn't been incremented yet
while (i < 1) //true
i++; //in the first executor thread
executor.submit(...) //IOOBE
我想知道你为什么不写信:
for (File f : fileList) {
executor.submit( ... ); //use f directly in the executor
}