我正在尝试编写一个使用Imgur的API根据帐户名下载图像的程序。
private volatile int threadCount;
private volatile double totalFileSize;
private volatile List<String> albums = new ArrayList<>();
private volatile Map<JSONObject, String> images = new HashMap<>();
private final ExecutorService executorService = Executors.newFixedThreadPool(100, (Runnable r) -> {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
});
private void downloadAlbums(List<String> albums) {
threadCount = 0;
albums.forEach((albumHash) -> {
if (hasRemainingRequests()) {
incThreadCount();
executorService.execute(() -> {
try {
String responseString;
String dirTitle;
String albumUrl = URL_ALBUM + albumHash;
String query = String.format("client_id=%s", URLEncoder.encode(CLIENT_ID, CHARSET));
URLConnection connection = new URL(albumUrl + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", CHARSET);
InputStream response = connection.getInputStream();
try (Scanner scanner = new Scanner(response)) {
responseString = scanner.useDelimiter("\\A").next();
JSONObject obj = new JSONObject(responseString).getJSONObject("data");
dirTitle = obj.getString("title");
String temp = "";
// Get save path from a TextField somewhere else on the GUI
ObservableList<Node> nodes = primaryStage.getScene().getRoot().getChildrenUnmodifiable();
for (Node node : nodes) {
if (node instanceof VBox) {
ObservableList<Node> vNodes = ((VBox) node).getChildrenUnmodifiable();
for (Node vNode : vNodes) {
if (vNode instanceof DestinationBrowser) {
temp = ((DestinationBrowser) vNode).getDestination().trim();
}
}
}
}
final String path = temp + "\\" + formatPath(accountName) + "\\" + formatPath(dirTitle);
JSONArray arr = obj.getJSONArray("images");
arr.forEach((jsonObject) -> {
totalFileSize += ((JSONObject) jsonObject).getDouble("size");
images.put((JSONObject) jsonObject, path);
});
}
} catch (IOException ex) {
//
} catch (Exception ex) {
//
} finally {
decThreadCount();
if (threadCount == 0) {
Platform.runLater(() -> {
DecimalFormat df = new DecimalFormat("#.#");
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);// 714833218
alert.setHeaderText("Found " + images.size() + " images (" + (totalFileSize < 1000000000 ? df.format(totalFileSize / 1000000) + " MB)" : df.format(totalFileSize / 1000000000) + " GB)"));
alert.setContentText("Proceed with download and save images?");
Optional<ButtonType> alertResponse = alert.showAndWait();
if (alertResponse.get() == ButtonType.OK) {
progressBar.setTotalWork(images.size());
executorService.execute(() -> {
for (JSONObject obj : images.keySet()) {
(new File(images.get(obj))).mkdirs();
downloadImage(obj, images.get(obj));
}
});
}
});
}
}
});
}
});
}
albums
是将GET请求发送到Imgur以便接收该专辑的图像所需的代码列表。然后,将返回的数据用于下载图像本身的另一种方法中。
现在,所有这些工作正常,但是当程序发出所有GET请求时,JavaFX线程将挂起(GUI变得无响应)。并且,在执行完所有GET请求之后,JavaFX线程停止挂起,并且alert
显示正确的信息。
我只是不明白为什么当我没有(我相信我没有)阻止它的线程并且我正在使用ExecutorService
来执行所有网络请求时,GUI变得无响应。