我有一個空指針異常,因爲在列表adPics
處有一些空值。它很少發生。這怎麼可能?排序時出現非常奇怪的NullPointerException
(並行此代碼下載圖像,並將它們保存在本地。)
List<String> downloadAdImages(List<String> imagesUrls, final String itemFolder) {
final List adPics = new ArrayList<>();
final ExecutorService executor = newFixedThreadPool(20);
imagesUrls.forEach(
picUrl -> executor.submit(() -> {
try {
String imageNewFileName = imagesUrls.indexOf(picUrl) + "." + getExtension(picUrl);
String bigPicUrl = picUrl.replace("b.jpg", "ab.jpg"); // big version
copyURLToFile(new URL(bigPicUrl), new File(itemFolder, imageNewFileName), 10, 10);
adPics.add(imageNewFileName);
} catch (IOException ex) {
log.log(Level.WARNING, "Could not download image {0} ({1})", new Object[]{picUrl, ex.getMessage()});
}
}));
executor.shutdown();
try {
executor.awaitTermination(15L, MILLISECONDS);
} catch (InterruptedException ex) {
log.log(Level.WARNING, "Could not wait for all images downloads");
}
Collections.sort(adPics); // null values at list lead to NPE here. How are there null values?
return adPics;
}
有時adPics
列表有null
值。這是NPE的原因。但是如何?分析線程中執行的代碼,不可能添加null
值。如果下載圖像時出現問題,則會引發IOException。 imageNewFileName
不能是null
。
此代碼是Java 8,它使用Apache Commons IO lib。
(關於問題,而不是downvotes)我想這是因爲你正在添加到來自多個線程的列表,但列表未正確同步。有趣的事情可以發生在你這樣做的時候。 – sstan
您確定'awaitTermination'調用沒有超時,並且您在開始對adPics進行排序的同時向其添加元素?不知道爲什麼會拋出一個NPE,但'ArrayList'不是線程安全的,所以我猜想任何事情都可能發生。 – Tunaki
嗯..謝謝@sstan我會嘗試使用http://stackoverflow.com/questions/11360401/java-synchronized-list –