如何异步调用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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:13:36  来源:igfitidea点击:

How to asynchronously call a method in Java

javaconcurrencyasynchronousgoroutine

提问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.concurrentpackage (for example, ScheduledExecutorService), but FutureTaskmay 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 FutureTaskbecame 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.

FutureTaskis 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 @Asyncannotation 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/

参考: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

You can use AsyncFuncfrom Cactoos:

您可以AsyncFuncCactoos使用:

boolean matches = new AsyncFunc(
  x -> x.matches("something")
).apply("The text").get();

It will be executed at the background and the result will be available in get()as a Future.

它会在后台执行,其结果将是可用get()Future

回答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.
});