Java中如何异步调用方法
我最近一直在研究 Go 的 goroutines 并认为有类似的东西会很好在爪哇。据我搜索,并行化方法调用的常见方法是执行以下操作:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
这不是很优雅。 有更好的方法吗? 我在项目中需要这样的解决方案,因此我决定围绕异步方法调用实现我自己的包装器类。
我在 J-Go 中发布了我的包装类。但我不知道这是否是一个好的解决方案。用法很简单:
SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10); //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get()); //Blocks until intReturningMethod returns
或者不太冗长:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
在内部,我使用一个实现 Runnable 的类,并执行一些反射工作来获取正确的方法对象并调用它。
我想要一些关于我的小库以及关于在 Java 中进行像这样的异步方法调用的主题的意见。安全吗?已经有更简单的方法了吗?
I've been looking at Go's goroutines lately and thought it would be nice to have something similar in Java. As far as I've searched the common way to parallelize a method call is to do something like:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
Thats not very elegant. Is there a better way of doing this? I needed such a solution in a project so I decided to implement my own wrapper class around a async method call.
I published my wrapper class in J-Go. But I don't know if it is a good solution. The usage is simple:
SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10); //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get()); //Blocks until intReturningMethod returns
or less verbose:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
Internally I'm using a class that implements Runnable and do some Reflection work to get the correct method object and invoking it.
I want some opinion about my tiny library and on the subject of making async method calls like this in Java. Is it safe? Is there already a simplier way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
我刚刚发现有一种更干净的方法可以做到这一点
(至少在 Java 8 中),您可以使用 lambda 表达式将其缩短为:
就像在 JS 中创建函数一样简单!
I just discovered that there is a cleaner way to do your
(At least in Java 8), you can use a lambda expression to shorten it to:
As simple as making a function in JS!
Java 8引入了CompletableFuture,可在java.util.concurrent.CompletableFuture包中使用,可用于进行异步调用:
Java 8 introduced CompletableFuture available in package java.util.concurrent.CompletableFuture, can be used to make a asynch call :
您可能还希望考虑类
java.util.concurrent.FutureTask
。如果您使用的是 Java 5 或更高版本, FutureTask 是“可取消的异步计算”的交钥匙实现。
java.util.concurrent
包中提供了更丰富的异步执行调度行为(例如ScheduledExecutorService
),但是FutureTask
可能拥有所有您需要的功能。我什至会说,自从
FutureTask
可用以来,不再建议使用您给出的第一个代码模式作为示例。 (假设您使用的是 Java 5 或更高版本。)You may wish to also consider the class
java.util.concurrent.FutureTask
.If you are using Java 5 or later, FutureTask is a turnkey implementation of "A cancellable asynchronous computation."
There are even richer asynchronous execution scheduling behaviors available in the
java.util.concurrent
package (for example,ScheduledExecutorService
), butFutureTask
may have all the functionality you require.I would even go so far as to say that it is no longer advisable to use the first code pattern you gave as an example ever since
FutureTask
became available. (Assuming you are on Java 5 or later.)我不喜欢为此使用反射的想法。
不仅在某些重构中丢失它很危险,而且它也可能被
SecurityManager
拒绝。与 java.util.concurrent 包中的其他选项一样,
FutureTask
是一个不错的选择。我最喜欢的简单任务:
比创建线程短一点(任务是 Callable 或 Runnable)
i don't like the idea of using Reflection for that.
Not only dangerous for missing it in some refactoring, but it can also be denied by
SecurityManager
.FutureTask
is a good option as the other options from the java.util.concurrent package.My favorite for simple tasks:
little bit shorter than creating a Thread (task is a Callable or a Runnable)
您可以使用 CompletableFuture 的 Java8 语法,这样您就可以根据调用异步函数的结果执行额外的异步计算。
例如:
更多详细信息可以在这篇文章中找到
You can use the Java8 syntax for CompletableFuture, this way you can perform additional async computations based on the result from calling an async function.
for example:
More details can be found in this article
您可以使用
@Async
注释http://aspects.jcabi.com" rel="noreferrer">jcabi-aspects 和 AspectJ:当您调用
save()
时,一个新线程启动并执行其主体。您的主线程将继续执行,无需等待save()
的结果。You can use
@Async
annotation from jcabi-aspects and AspectJ:When you call
save()
, a new thread starts and executes its body. Your main thread continues without waiting for the result ofsave()
.Java 还提供了一种调用异步方法的好方法。在java.util.concurrent中,我们有ExecutorService来帮助做同样的事情。像这样初始化你的对象 -
然后调用函数 -
Java also provides a nice way of calling async methods. in java.util.concurrent we have ExecutorService that helps in doing the same. Initialize your object like this -
and then call the function like-
您可以为此使用 Future-AsyncResult。
参考:https://spring.io/guides/gs/async-method/
You can use Future-AsyncResult for this.
Reference: https://spring.io/guides/gs/async-method/
您可以使用
AsyncFunc
来自 Cactoos:它将在后台执行,结果将在
get()
作为Future
。You can use
AsyncFunc
from Cactoos:It will be executed at the background and the result will be available in
get()
as aFuture
.Java 21+:
或者(如果您由于某种原因不需要虚拟线程):
Java 21+:
Or (if you don't want a virtual thread for some reason):
这可能不是一个真正的解决方案,但现在 - 在 Java 8 中 - 您可以使用 lambda 表达式使此代码看起来至少好一点。
您甚至可以在一行中完成此操作,并且仍然具有良好的可读性。
It's probably not a real solution, but now - in Java 8 - You can make this code look at least a little better using lambda expression.
And You could even do this in one line, still having it pretty readable.
这并不是真正相关,但如果我要异步调用一个方法,例如 matches(),我会使用:
然后调用我会使用的异步方法:
我已经测试过它并且它有效。只是认为如果其他人只是为了“异步方法”而来,这可能会对他们有所帮助。
This is not really related but if I was to asynchronously call a method e.g. matches(), I would use:
Then to call the asynchronous method I would use:
I have tested this and it works. Just thought it may help others if they just came for the "asynchronous method".
EA 还为 Async-Await 创建了一个不错的库: https://github.com/electronicarts/ea -async
来自自述文件:
使用 EA Async
不使用 EA Async
There is also nice library for Async-Await created by EA: https://github.com/electronicarts/ea-async
From their Readme:
With EA Async
Without EA Async