【发布时间】:2017-10-07 03:14:48
【问题描述】:
我正在使用 Javafx 设计一个多线程应用程序,并希望有一个 TableView,其中包含每个线程的名称和进度列。经过大量研究后,我在这里找到了一个类似的示例:
JavaFX Update progressbar in tableview from Task
(指向这个:'https://community.oracle.com/message/10999916')
然而,我遇到的问题在这个例子中得到了很好的说明;如何多次调用“任务”对象来更新 ProgressIndicator?
我对 Oracle 文档的理解是,Task 对象“是一次性类,不能重用”。这样看来,一个任务对象的 call() 方法只能调用一次。我需要在任务通过 Thread 类的过程中多次更新它,而不是调用一次并通过 For 循环任意递增。
我已阅读有关绑定到侦听器和创建服务类的信息,但我不确定这些是否是此问题的实际解决方案。因此,我想问一下这在 Javafx 中是否可行,或者我是否忽略了某些东西。如果过去有人已经做到了这一点,如果您能够通过前面提供的示例说明如何做到这一点,那将非常有帮助。
对此的任何指导将不胜感激,谢谢。
-画了
编辑 1:我编辑了我的措辞,因为它不准确。
编辑 2:这是一个带有一些伪代码的示例。假设我有一堂课,代码如下:
public static class TaskEx extends Task<Void>{
@Override
protected Void call(){
updateProgress(.5, 1);
return null
}
public static void callThread() {
TableView<TaskEx> table = new TableView<TaskEx>();
//Some code for data in table.
TableColumn progressColumn = new TableColumn ("Progress");
progressColumn.setCellValueFactory(new PropertyValueFactor("progress");
table.setItems(<data>);
table.getColumns();addAll(progressColumn);
ExecutorService executor = Executors.newFixedThreadPool(<SomeNumber>);
for(TaskEx task : table.getItems(){
Threading.ThreadClass newThread = new Threading.ThreadClass(task);
executor.submit(newThread, <uniqueID>);
}
}
然后说我有第二个线程类的逻辑:
static class ThreadClass extends Thread{
Task progressTask;
public ThreadClass(Task task, Integer id){
progressTask = task;
}
public void run(){
ExecutorService executor = Executors.newFixedThreadPool(<someNumber>);
//This invokes the Task call for the correct progressIndicator in the Tableview.
//It will correctly set the progressIndicator to 50% done.
executor.submit(progressTask);
/* Main logic of the Threading class that involves the 'id' passed in. */
//This will do nothing because you cannot invoke the Task call more than once.
executor.submit(progressTask);
}
}
这是我需要的工作流程,但我不确定如何完成。
【问题讨论】:
-
“这样看来,一个任务对象只能调用一次'updateProgress'。” 这显然不是真的:您链接的示例调用
updateProgress(...)in一个循环,因此每个任务都会多次调用它。所有文档意味着您只能调用一次Task的call()方法。您可以在call()方法中多次调用updateProgress。您链接的示例似乎是您描述您想要做的事情的完整实现。你能解释一下你的问题有什么不同吗? -
嘿詹姆斯。我确定我措辞很糟糕。我的意思是,为了正确增加任务的进度,我需要多次调用任务的 call() 方法。我知道一旦我在 call() 方法中,我可以循环并继续调用 updateProgress,但我不知道当我调用它时线程需要多长时间才能完成。我曾计划在任务的 call() 方法位于线程逻辑中的某个点时调用它一次,然后在它进一步下降时再次调用它,依此类推。
-
我想你一定误解了
Task的目的?任务代表“你正在做的事情”——所以它应该是你感兴趣的任务的进度。如果不是这样,您使用Task做什么?你能发布一些代码来说明这个问题吗? -
换句话说,
Task是线程执行的Runnable-call()方法本质上是run()的Runnable方法。Task是线程正在做的事情。 -
在我看来,你可能做错了。据我所知,您可能产生了 X 个线程(不使用
Task)同时执行 X 个不同的事情。然后每个衍生线程创建其Task并将进度更新回UI 线程(到单个ProgressBar)。如果这是您正在做的事情,那么您的Task是多余的 - 您不妨参考相应的ProgressBar并使用Platform.runLater(() -> progressBar.setProgress(x));来执行此操作。或者,您应该将它们转换为Task,而不是new Thread()。