排序时非常奇怪的 NullPointerException
Very odd NullPointerException while sorting
我有一个空指针异常,因为列表 adPics
中有一些空值。它很少发生。怎么可能?
(此代码并行下载图像并保存在本地。)
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
.
此代码是 Java8,它使用 Apache Commons IO 库。
方法 awaitTermination
不会停止您的 运行 线程。它只等到所有线程完成或达到 timeout
。因此您的线程仍在将项目添加到您的列表中。
另外你应该考虑下载和复制到文件系统是运行即使超时了。
一个简单但不完美的解决方案是在达到超时时设置一个标志,并在添加更多项目之前检查该标志。
更好的方法是在达到超时后中断线程。这还应该包括中断下载和文件复制。
您的代码有几个问题。保罗已经指出了一个问题。另一个问题是您正在同时访问 List adPics。
要在不使用同步列表的情况下解决您的问题,您可以创建一个 List[CompletableFuture] 并在最后调用 CompletableFuture.allOf。
每个 CompletableFuture 都应该 return image filename 但在尝试下载图像之前,它应该检查时间以查看是否要开始该操作。如果不是,您可以使用 null 值完成该 CompletableFuture。
在 CompletableFuture.allOf 中,您可以创建一个没有空值的新列表并对该列表进行排序。
我有一个空指针异常,因为列表 adPics
中有一些空值。它很少发生。怎么可能?
(此代码并行下载图像并保存在本地。)
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
.
此代码是 Java8,它使用 Apache Commons IO 库。
方法 awaitTermination
不会停止您的 运行 线程。它只等到所有线程完成或达到 timeout
。因此您的线程仍在将项目添加到您的列表中。
另外你应该考虑下载和复制到文件系统是运行即使超时了。
一个简单但不完美的解决方案是在达到超时时设置一个标志,并在添加更多项目之前检查该标志。
更好的方法是在达到超时后中断线程。这还应该包括中断下载和文件复制。
您的代码有几个问题。保罗已经指出了一个问题。另一个问题是您正在同时访问 List adPics。
要在不使用同步列表的情况下解决您的问题,您可以创建一个 List[CompletableFuture] 并在最后调用 CompletableFuture.allOf。 每个 CompletableFuture 都应该 return image filename 但在尝试下载图像之前,它应该检查时间以查看是否要开始该操作。如果不是,您可以使用 null 值完成该 CompletableFuture。 在 CompletableFuture.allOf 中,您可以创建一个没有空值的新列表并对该列表进行排序。