153

私は最近、 Go のゴルーチンを見ていて、Java に似たようなものがあるといいなと思いました。メソッド呼び出しを並列化する一般的な方法を検索した限り、次のようなことを行います。

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 でこのような非同期メソッド呼び出しを行うことについて意見が欲しいです。安全ですか?もっと簡単な方法はすでにありますか?

4

12 に答える 12

34

クラスについても検討することをお勧めしますjava.util.concurrent.FutureTask

Java 5 以降を使用している場合、FutureTaskは「キャンセル可能な非同期計算」のターンキー実装です。

java.util.concurrentパッケージには、さらに豊富な非同期実行スケジューリング動作( などScheduledExecutorService) が用意されていFutureTaskますが、必要な機能がすべて含まれている場合があります。

利用可能になって以来、あなたが例として挙げた最初のコードパターンを使用することはもはやお勧めできませんFutureTask。(Java 5 以降を使用していると仮定します。)

于 2009-12-03T21:31:55.527 に答える
24

そのためにリフレクションを使用するという考えは好きではありません。
一部のリファクタリングでそれを見逃すと危険であるだけでなく、SecurityManager.

FutureTaskjava.util.concurrent パッケージの他のオプションと同様に、適切なオプションです。
単純なタスクでの私のお気に入り:

    Executors.newSingleThreadExecutor().submit(task);

スレッドを作成するよりも少し短い (タスクは Callable または Runnable です)

于 2009-12-03T22:32:46.633 に答える
11

jcabi-aspectsと AspectJの@Asyncアノテーションを使用できます。

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

を呼び出すsave()と、新しいスレッドが開始され、その本体が実行されます。メインスレッドは の結果を待たずに続行しsave()ます。

于 2014-06-05T05:25:11.027 に答える
8

これには 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/

于 2015-06-23T14:15:56.120 に答える
2

それはおそらく本当の解決策ではありませんが、Java 8 では、ラムダ式を使用して、このコードの外観を少なくとも少し良くすることができます。

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

そして、これを 1 行で行うこともできますが、それでもかなり読みやすくなっています。

new Thread(() -> x.matches("something")).start();
于 2015-10-31T21:36:32.310 に答える