如何在Java中asynchronous调用一个方法

我最近一直在看Go的goroutine ,认为在Java中有类似的东西会很好。 就我所寻找的并行化方法调用的常见方式而言,就是做类似的事情:

final String x = "somethingelse"; new Thread(new Runnable() { public void run() { x.matches("something"); } }).start(); 

那不是很优雅。 有没有更好的方法来做到这一点? 我在一个项目中需要这样的解决scheme,所以我决定围绕asynchronous方法调用实现我自己的包装类。

我在J-Go上发布了我的包装类。 但是我不知道这是不是一个好的解决scheme。 用法很简单:

 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 

或更less冗长:

 Go.with(obj).callLater("myRandomMethod"); //... Go away if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended System.out.println("Method is finished!"); 

在内部,我使用了一个实现了Runnable的类,并做了一些Reflection工作来获取正确的方法对象并调用它。

我想对我的小型库和关于在Java中使用这种asynchronous方法调用的问题有一些看法。 安全吗? 有没有更简单的方法?

我刚刚发现,有一个更干净的方式来做你的

 new Thread(new Runnable() { public void run() { //Do whatever } }).start(); 

(至less在Java 8中),可以使用lambdaexpression式将其缩短为:

 new Thread(() -> { //Do whatever }).start(); 

就像在JS中做一个函数一样简单!

你也可以考虑类java.util.concurrent.FutureTask

如果您正在使用Java 5或更高版本, FutureTask是“可取消的asynchronous计算”的交钥匙实现。

java.util.concurrent包中提供了更丰富的asynchronous执行调度行为(例如ScheduledExecutorService ),但FutureTask可能具有您需要的所有function。

我甚至会说,自从FutureTask开始使用以后,第一个代码模式就不再是可取的了。 (假设您使用的是Java 5或更高版本)

我不喜欢使用reflection的想法。
不仅在一些重构中丢失它是很危险的,但它也可以被SecurityManager拒绝。

作为java.util.concurrent包中的其他选项, FutureTask是一个很好的select。
我最喜欢简单的任务:

  Executors.newSingleThreadExecutor().submit(task); 

比创build一个线程短一点(任务是一个Callable或一个Runnable)

您可以使用@Async -aspects和AspectJ中的@Async注释:

 public class Foo { @Async public void save() { // to be executed in the background } } 

当你调用save() ,一个新线程启动并执行它的主体。 您的主线程继续而不等待save()的结果。

您可以使用CompletionFuture的Java8语法,这样您可以根据调用asynchronous函数的结果执行其他asynchronous计算。

例如:

  CompletableFuture.supplyAsync(this::findSomeData) .thenApply(this:: intReturningMethod) .thenAccept(this::notify); 

更多细节可以在这篇文章中find

你可以使用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); } 

参考: https : //spring.io/guides/gs/async-method/

这不是真正的相关,但如果我要asynchronous调用一个方法,例如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); } }); } 

然后调用我将使用的asynchronous方法:

 String x = "somethingelse"; try { System.out.println("Matches: "+matches(x, "something").get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } 

我已经testing了这个,它的工作原理。 只是认为它可以帮助别人,如果他们只是来“asynchronous方法”。

您可以使用AsyncFunc的AsyncFunc :

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

它将在后台执行,结果将作为Futureget()可用。

这可能不是一个真正的解决scheme,但现在 – 在Java 8中 – 您可以使用lambdaexpression式使代码看起来更好一点。

 final String x = "somethingelse"; new Thread(() -> { x.matches("something"); } ).start(); 

你甚至可以在一行中做到这一点,仍然具有可读性。

 new Thread(() -> x.matches("something")).start();