我对多线程相当新,并且在我的应用程序中使任务工作遇到了一些困难。
我有一个文件浏览器,允许用户选择要导入的文件,当导入正在进行时,我正在尝试更新屏幕底部的进度条。但是,我试图避免使酒吧"不确定"对于导入过程,而是填写实际的导入进度。
为了实现这一目标,我创建了2个任务,1个用于获取要从文件浏览器树中的选定项目导入的文件的总数,第2个用于实际导入歌曲并更新进度条在一个简单的等式上使用第一个任务的总计数。
但是,我不确定如何将第一个任务的int值转换为第二个任务。
这也提出了一些额外的问题,首先是关于让事情发挥作用,其次是关于我的设计的性能方面。
控制器类
@FXML
private void handleImportButtonAction(ActionEvent event) {
new Thread(getSelectedFilesLeafCountTask).start();
new Thread(importSongsTask).start();
}
获取叶子计数任务
@Component
public class GetSelectedFilesLeafCountTask extends Task<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
@Autowired
private FooterController footerController;
private Integer leafCount = 0;
@Override
protected Integer call() throws Exception {
Platform.runLater(new Runnable(){
footerController.getTaskProgressIndicator().setProgress(ProgressBar.INDETERMINITE);
footerController.getTaskLabel().setText("Indexing Files");
});
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().
getSelectionModel().getSelectedItems());
return leafCount;
}
// Recursively counts the leaves within a single or group of Files
private void getSelectedItemsLeafCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
}
导入歌曲任务
@Component
public class ImportSongsTask implements Runnable {
@Autowired
FileBrowserController fileBrowserController;
@Autowired
FooterController footerController;
@Autowired
ConsoleTabController consoleTabController;
@Autowired
DataModel datamodel;
private double totalFileCount; // This is the value needed from task1
private double completionCount;
private int importCount; // Total Number of Files that have been imported at the end of the task
private int failCount;
@Override
public void run() {
importCount = 0;
failCount = 0;
totalFileCount = fileBrowserController.getSelectedLeafCount();
Platform.runLater(new Runnable() {
@Override
public void run() {
footerController.getTaskLabel().setText(footerController.IMPORTING_FILES_MSG);
footerController.getTaskProgressIndicator().setProgress(0.0);
footerController.getTaskProgressIndicator().setVisible(true);
}
});
List<Song> importSongsList = new ArrayList<>();
importSongsList = importFilesForImportButton(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems(), importSongsList);
datamodel.getWindowDisplaySongs().addAll(importSongsList);
Platform.runLater(new Runnable() {
@Override
public void run() {
// Reset button and progress bar values
completionCount = 0;
}
});
}
private List<Song> importFilesForImportButton(List<TreeItem<File>> files, List<Song> importList){
for(TreeItem<File> f : files) {
try {
if(f.isLeaf() && !datamodel.songWindowContainsFile(f.getValue())) {
// Perform Processing
Platform.runLater(new Runnable() {
@Override
public void run() {
footerController.getTaskProgressIndicator().setProgress((completionCount / totalFileCount)); // Need the value from task 1 here
}
});
completionCount++;
importCount++;
}else{
importFilesForImportButton(f.getChildren(), importList);
}
}catch(Exception e) {
}
}
return importList;
}
}
其他问题
是否有更好的性能解决方案允许我根据总文件数更新进度条,不需要我遍历所有文件2次(一次获取进度条的总计数,然后是实际导入它们的第二个)?
我是否有办法启动任务来计算导入任务中的叶子项,但确保导入任务不会继续,直到计数任务100%完成?因为我只需要从其他后台任务中启动该任务,但我不确定如何确保它首先完成。