如何用Java编写这个等效代码?(How can I write this equivalent code in Java?)

编程入门 行业动态 更新时间:2024-10-25 10:32:44
如何用Java编写这个等效代码?(How can I write this equivalent code in Java?)

我有一个异步C ++函数,需要将工作传递给另一个线程,然后等待该工作完成。 我使用std::promise对象完成了这个,如下所示:

void task(std::function<void()> const& func) { std::promise<void> promise; //You can think of 'thread_pool' as being a wrapper around a std::vector<std::thread> //where all the threads have a body that more-or-less look like /* void run() { * while(running) { * task t; * if(task_queue.try_pop(t)) t(); * } * } */ thread_pool.post([&] { try { func(); promise.set_value(); } catch (...) { promise.set_exception(std::current_exception()); } }); promise.get_future().get(); }

所以我的问题是,在Java中表达相同概念的最简单方法是什么? 在我的特定情况下,我需要管理Swing线程和JavaFX线程之间的通信,并管理两者之间的任务。 这是我到目前为止:

public static void runAndWait(Runnable runner) { Future<Object> future = new FutureTask<>(new Callable<Object>() { public Object call() { try { runner.run(); } catch (RuntimeException e) { //??? How do I report the exception to the future? } return null; } }); Platform.runLater(/*How do I run the future I've just created?*/); future.get();//I want the exception to throw here if we caught one. }

但显然,我缺少一些东西。 如何表达我在Java中描述的C ++代码?

I've got an asynchronous C++ function that needs to pass work to another thread and then wait for that work to finish. I've done this using a std::promise object, like so:

void task(std::function<void()> const& func) { std::promise<void> promise; //You can think of 'thread_pool' as being a wrapper around a std::vector<std::thread> //where all the threads have a body that more-or-less look like /* void run() { * while(running) { * task t; * if(task_queue.try_pop(t)) t(); * } * } */ thread_pool.post([&] { try { func(); promise.set_value(); } catch (...) { promise.set_exception(std::current_exception()); } }); promise.get_future().get(); }

So my question is, what is the simplest way to express the same concept in Java? In my specific case, I need to manage communication between a Swing thread and a JavaFX thread, and manage tasks between the two. This is what I have so far:

public static void runAndWait(Runnable runner) { Future<Object> future = new FutureTask<>(new Callable<Object>() { public Object call() { try { runner.run(); } catch (RuntimeException e) { //??? How do I report the exception to the future? } return null; } }); Platform.runLater(/*How do I run the future I've just created?*/); future.get();//I want the exception to throw here if we caught one. }

Obviously, though, I'm missing a few things. How can I express the C++ code I described in Java?

最满意答案

这个问题似乎类似于:

从javafx platform runlater返回结果

而你问题中的runAndWait代码与Sarcan的答案非常相似,这就是:

final FutureTask query = new FutureTask(new Callable() { @Override public Object call() throws Exception { return queryPassword(); } }); Platform.runLater(query); System.out.println(query.get());

在对其他答案的评论中,我注意到您也关注异常处理。 您会注意到FutureTask具有setException()逻辑:

导致此未来报告ExecutionException,并将给定的throwable作为其原因,除非此未来已设置或已取消。 在计算失败时, run()方法在内部调用此方法。

由于内部实现调用setException调用,因此您无需显式调用setException 。 FutureTask上下文中抛出的任何未捕获的异常都将在FutureTask中设置,您可以通过从future.get()调用中捕获ExecutionException来解释它。

// non-JavaFX thread code... Future<Void> future = new FutureTask<>(() -> { // work to be done on the JavaFX thread... return null; } }); // do the work on the JavaFX thread. Platform.runLater(future); try { // await completion of the work on the JavaFX thread. future.get(); } catch (InterruptedException ex) { // restore the interrupt status (see the linked Goetz article). Thread.currentThread().interrupt(); } catch (ExecutionException ex) { // exception handling logic for an exception occurring // in the body of the FutureTask here. }

在上面的示例中,我有一个Future<Void>因为我对从Future调用传递任何数据结果不感兴趣。 如果我对获得结果感兴趣,那么我可以使用Future<SomeObjectType>并使SomeObjectType result = future.get() 。 在这种情况下,我喜欢尽可能多地使用不可变对象 (例如对于SomeObjectType ),尽管对于future.get()场景并不是绝对必要的,因为它本质上是按顺序访问对象而不是跨线程并行访问。

如果您想在非JavaFX线程上重新抛出JavaFX应用程序线程上发生的异常,那么您可以这样做:

} catch (ExecutionException ex) { throw ex.getCause(); }

以下信息适用于与JavaFX(或一般Java)不同的基于线程的交互,并且与问题没有直接关系,因此可以忽略回答问题的细节,它仅用作背景信息。

一些背景信息:我发现在Java中执行任务非常出色,是Brian Goetz的文章:

处理InterruptedException 。

相反的交互:上面给出的示例涉及从另一个线程调用JavaFX应用程序线程上的任务并等待它们完成。 如果您想要在另一个线程而不是JavaFX线程上调用Task,那么您将使用JavaFX Task 。 在这种情况下,您不希望JavaFX线程等待非JavaFX任务的完成,因为您不应该暂停或挂起JavaFX线程(而是必须同时执行Task调用,如何在链接中解释这一点)任务Javadoc)。

在相关(但不同)的问题中详细介绍了后台线程和JavaFX UI之间的交互机制:

JavaFX2:我可以暂停后台任务/服务吗?

This question seems similar to:

Return result from javafx platform runlater

And the runAndWait code from your question looks very similar to Sarcan's answer, which is this:

final FutureTask query = new FutureTask(new Callable() { @Override public Object call() throws Exception { return queryPassword(); } }); Platform.runLater(query); System.out.println(query.get());

In comments on other answers I notice you are also concerned about Exception handling. You will notice that FutureTask has logic to setException():

Causes this future to report an ExecutionException with the given throwable as its cause, unless this future has already been set or has been cancelled. This method is invoked internally by the run() method upon failure of the computation.

As the internal implementation invokes the setException call, you don't need to explicitly invoke setException. Any uncaught exception thrown in the context of the FutureTask will be set in that FutureTask and you can interpret it via catching an ExecutionException from your future.get() call.

// non-JavaFX thread code... Future<Void> future = new FutureTask<>(() -> { // work to be done on the JavaFX thread... return null; } }); // do the work on the JavaFX thread. Platform.runLater(future); try { // await completion of the work on the JavaFX thread. future.get(); } catch (InterruptedException ex) { // restore the interrupt status (see the linked Goetz article). Thread.currentThread().interrupt(); } catch (ExecutionException ex) { // exception handling logic for an exception occurring // in the body of the FutureTask here. }

In the sample above I have a Future<Void> as I am not interested in passing any data result from the Future call. If I were interested in getting a result, then I could use Future<SomeObjectType> and have SomeObjectType result = future.get(). In situations like this I like to use immutable objects as much as possible (for example for SomeObjectType), though it is not strictly necessary for the future.get() scenario as that essentially is accessing objects in sequence rather than in parallel across threads.

If you wanted to re-throw the exception that occurred on the JavaFX application thread on the non-JavaFX thread, then you could do this:

} catch (ExecutionException ex) { throw ex.getCause(); }

The following information is for different thread based interactions with JavaFX (or Java in general) and does not directly relate to the question, so it can be ignored for the specifics of answering the question, it merely serves as background info.

Some background info: I find a really excellent on implementation of tasks in Java to be Brian Goetz's article:

Dealing with InterruptedException.

Opposite interaction: The example given above relates to invoking tasks on the JavaFX application thread from another thread and awaiting their completion. If you have the opposite situation where you want to invoke a Task on another thread instead of the JavaFX thread, then you would use a JavaFX Task. In such a case you don't want the JavaFX thread to await completion of the non-JavaFX task as you should never pause or suspend the JavaFX thread (instead the Task call must be executed concurrently, how to do this is explained in the linked Task Javadoc).

There are mechanisms for interacting between the background thread and the JavaFX UI detailed in the related (but different) question:

JavaFX2: Can I pause a background Task / Service?

更多推荐

本文发布于:2023-07-29 20:06:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1319371.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何用   代码   Java   code   write

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!