JavaFX任务可调用
我正在开发一个JavaFX应用程序,并在ExecutorServiceJavaFX任务可调用,java,multithreading,javafx,Java,Multithreading,Javafx,我正在开发一个JavaFX应用程序,并在ExecutorServicesubmit方法中提供JavaFX任务。此外,我还试图在Future对象中提交的返回值中获取任务的返回值。然后我发现ExecutorService只在提交Callable对象时返回值,尽管有call方法,JavaFX任务仍然可以运行。那么,这个问题有什么解决办法吗 我试着用这种方式解决了我的问题,但当我不想写自己的课程时,我愿意接受建议 我的主要方法是: public static void main(String[] arg
submit
方法中提供JavaFX任务。此外,我还试图在Future
对象中提交的返回值中获取任务的返回值。然后我发现ExecutorService
只在提交Callable
对象时返回值,尽管有call
方法,JavaFX任务仍然可以运行。那么,这个问题有什么解决办法吗
我试着用这种方式解决了我的问题,但当我不想写自己的课程时,我愿意接受建议
我的主要方法是:
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Semaphore semaphore = new Semaphore(1);
List<Integer> list = IntStream.range(0,100).boxed().collect(Collectors.toList());
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
List<Integer> sendingList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
sendingList.add(iterator.next());
}
System.out.println("SUBMITTING");
Future<Integer> future = executorService.submit((Callable<Integer>) new TestCallable(sendingList,semaphore));
System.out.println(future.get());
semaphore.acquire();
}
executorService.shutdown();
System.out.println("COMPLETED");
}
Task
扩展了java.util.concurrent.FutureTask
,从而实现了Future
接口。这意味着您可以像使用未来任务一样使用任务
Executor executor = ...;
Task<?> task = ...;
executor.execute(task);
task.get(); // Future method
如果您不需要Task
提供的功能,那么最好直接使用Runnable
或Callable
。这里不太清楚您想做什么
首先,您的信号量
不起任何作用,因为您使用了Executors.newSingleThreadExecutor()
,它已经保证在任何时间点只能运行一个任务
其次,正如@Slaw所提到的,您可能会阻塞JavaFX应用程序线程,这取决于您的实际实现(您的示例实际上不是JavaFX应用程序)
接下来,ExecutorService
为submit()
提供了两个主要重载
第一个重载接受一个可调用的
。此重载允许您检索Callable
(通过在返回的Future
上调用get()
)返回的值,因为Callable
指的是可以调用的内容-它可以返回值
第二个重载接受一个可运行的。由于Task
实现了Future
RunnableFuture
接口,并且Future
RunnableFuture
接口扩展了RunnableFuture
接口,因此传入Task
相当于调用此重载。此重载不希望返回结果,因为Runnable
是在没有结果的情况下运行的东西。在此重载返回的Future
上调用get()
将被阻止,直到任务完成,并且null
将被返回。如果需要检索由任务返回的值,则需要调用任务的get()
,而不是由ExecutorService.submit()返回的Future
根据OP的评论进行编辑
首先,由于调用方法已经在后台线程中运行,并且所有任务都应该按顺序(而不是并行)运行,因此您应该在不使用所有这些额外的ExecutorService
和Task
的情况下运行它们,除非有其他原因必须这样做
其次,列表
对象只不过是一个进行引用的对象。真正影响性能的是,您正在将元素的引用复制到新列表中。如果索引已知,则可以使用,因为返回的列表将使用与原始列表相同的支持数组,因此没有额外的O(n)
复制操作。您确实注意到a)任务
实现未来
b)提交任务并立即调用get
会导致在调用中等待并等待任务完成。你可以直接在线程上执行任务。如果我有一个多线程执行器,如果没有可用线程,我想等待,而不是每个任务?调用Future.get
确保等待任务完成。假设提交线程和执行任务的线程具有相同的优先级,则在不同线程上运行任务不会更快,并且不会导致任何任务并行运行,即使使用多线程执行器也是如此。在这种情况下,提交任务会将工作从一个线程移动到另一个线程,并使提交任务在等待任务完成时保持忙碌……我的信号灯在那里,确保我在准备运行新线程之前创建每个子列表。在我的实际应用程序中,列表要大得多,提交它们会占用大量内存并阻塞CPU。此外,在我的应用程序中,我在另一个后台守护进程线程上运行executor,因此它不会冻结我的GUI。这只是一个测试代码。“因为Task
实现了Future
接口,而Future
接口扩展了Runnable
接口…”<代码>未来
不扩展可运行
。我相信您正在考虑RunnableFuture
(它是通过扩展FutureTask
实现的Task
)。
Executor executor = ...;
Task<?> task = ...;
executor.execute(task);
task.get(); // Future method
Executor executor = ...;
Task<?> task = ...;
task.setOnSucceeded(event -> handleResult(task.getValue()));
task.setOnFailed(event -> handleException(task.getException()));
executor.execute(task);