如何异步调用Java中的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1842734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to asynchronously call a method in Java
提问by Felipe Hummel
I've been looking at Go's goroutineslately 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:
我最近一直在看Go 的 goroutines,并认为在 Java 中有类似的东西会很好。据我搜索,并行化方法调用的常用方法是执行以下操作:
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:
我在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
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.
在内部,我正在使用一个实现 Runnable 的类并做一些反射工作来获取正确的方法对象并调用它。
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?
我想对我的小库以及在 Java 中进行像这样的异步方法调用的主题发表一些意见。安全吗?已经有更简单的方法了吗?
回答by shadit
You may wish to also consider the class java.util.concurrent.FutureTask
.
你不妨也考虑一下类java.util.concurrent.FutureTask
。
If you are using Java 5 or later, FutureTaskis a turnkey implementation of "A cancellable asynchronous computation."
如果您使用的是 Java 5 或更高版本,FutureTask是“可取消异步计算”的交钥匙实现。
There are even richer asynchronous execution scheduling behaviors available in the java.util.concurrent
package (for example, ScheduledExecutorService
), but FutureTask
may have all the functionality you require.
包中还有更丰富的异步执行调度行为java.util.concurrent
(例如,ScheduledExecutorService
),但FutureTask
可能具有您需要的所有功能。
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.)
我什至会说,自从FutureTask
可用以来,不再建议使用您提供的第一个代码模式作为示例。(假设您使用的是 Java 5 或更高版本。)
回答by user85421
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
.
我不喜欢为此使用反射的想法。
不仅在某些重构中遗漏它是危险的,而且它也可以被SecurityManager
.
FutureTask
is a good option as the other options from the java.util.concurrent package.
My favorite for simple tasks:
FutureTask
作为 java.util.concurrent 包中的其他选项,是一个不错的选择。
我最喜欢的简单任务:
Executors.newSingleThreadExecutor().submit(task);
littlebit shorter than creating a Thread (task is a Callable or a Runnable)
小位比创建一个线程(任务是可赎回或一个Runnable)短
回答by yegor256
You can use @Async
annotation from jcabi-aspectsand AspectJ:
您可以使用jcabi-aspects和 AspectJ 中的@Async
注释:
public class Foo {
@Async
public void save() {
// to be executed in the background
}
}
When you call save()
, a new thread starts and executes its body. Your main thread continues without waiting for the result of save()
.
当您调用 时save()
,一个新线程将启动并执行其主体。您的主线程继续运行,无需等待save()
.
回答by AegisHexad
I just discovered that there is a cleaner way to do your
我刚刚发现有一种更清洁的方法来做你的
new Thread(new Runnable() {
public void run() {
//Do whatever
}
}).start();
(At least in Java 8), you can use a lambda expression to shorten it to:
(至少在 Java 8 中),您可以使用 lambda 表达式将其缩短为:
new Thread(() -> {
//Do whatever
}).start();
As simple as making a function in JS!
就像在 JS 中创建一个函数一样简单!
回答by FlameBlazer
This is not really related but if I was to asynchronously call a method e.g. matches(), I would use:
这并不是真正相关,但如果我要异步调用一个方法,例如matches(),我会使用:
private final static ExecutorService service = Executors.newFixedThreadPool(10);
public static Future<Boolean> matches(final String x, final String y) {
return service.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return x.matches(y);
}
});
}
Then to call the asynchronous method I would use:
然后调用我将使用的异步方法:
String x = "somethingelse";
try {
System.out.println("Matches: "+matches(x, "something").get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
I have tested this and it works. Just thought it may help others if they just came for the "asynchronous method".
我已经测试过这个并且它有效。只是认为如果他们只是为了“异步方法”而来,它可能会帮助其他人。
回答by user3177227
You can use Future-AsyncResult for this.
您可以为此使用 Future-AsyncResult。
@Async
public Future<Page> findPage(String page) throws InterruptedException {
System.out.println("Looking up " + page);
Page results = restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class);
Thread.sleep(1000L);
return new AsyncResult<Page>(results);
}
Reference: https://spring.io/guides/gs/async-method/
回答by kcpr
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.
这可能不是一个真正的解决方案,但现在 - 在 Java 8 中 - 您可以使用 lambda 表达式使这段代码看起来至少更好一点。
final String x = "somethingelse";
new Thread(() -> {
x.matches("something");
}
).start();
And You could even do this in one line, still having it pretty readable.
而且您甚至可以在一行中完成此操作,并且仍然具有很好的可读性。
new Thread(() -> x.matches("something")).start();
回答by yegor256
回答by Tal Avissar
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.
您可以对 CompletableFuture 使用 Java8 语法,这样您就可以根据调用异步函数的结果执行额外的异步计算。
for example:
例如:
CompletableFuture.supplyAsync(this::findSomeData)
.thenApply(this:: intReturningMethod)
.thenAccept(this::notify);
More details can be found in this article
更多细节可以在这篇文章中找到
回答by Rahul Chauhan
Java 8 introduced CompletableFuture available in package java.util.concurrent.CompletableFuture, can be used to make a asynch call :
Java 8 在包 java.util.concurrent.CompletableFuture 中引入了 CompletableFuture,可用于进行异步调用:
CompletableFuture.runAsync(() -> {
// method call or code to be asynch.
});