[java] 자바에서 비동기 적으로 메서드를 호출하는 방법

최근 에 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을 구현하는 클래스를 사용하고 있으며 올바른 메서드 개체를 가져 와서 호출하기 위해 몇 가지 Reflection 작업을 수행합니다.

내 작은 라이브러리와 Java에서 이와 같은 비동기 메서드 호출을 만드는 주제에 대한 의견이 필요합니다. 안전 해요? 이미 더 간단한 방법이 있습니까?



답변

나는 당신을 할 수있는 더 깨끗한 방법이 있음을 방금 발견했습니다.

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

(적어도 Java 8에서는) 람다 식을 사용하여 다음과 같이 줄일 수 있습니다.

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

JS에서 함수를 만드는 것처럼 간단합니다!


답변

Java 8은 java.util.concurrent.CompletableFuture 패키지에서 사용할 수있는 CompletableFuture를 도입했으며 비동기 호출을 만드는 데 사용할 수 있습니다.

CompletableFuture.runAsync(() -> {
    // method call or code to be asynch.
});


답변

수업을 고려할 수도 있습니다 java.util.concurrent.FutureTask.

Java 5 이상을 사용하는 경우 FutureTask 는 “취소 가능한 비동기 계산”의 턴키 구현입니다.

java.util.concurrent패키지 에서 사용할 수있는 더 풍부한 비동기 실행 스케줄링 동작 (예 :)이 ScheduledExecutorService있지만 FutureTask필요한 모든 기능이있을 수 있습니다.

심지어 사용 FutureTask가능해진 이후로 예제로 제공 한 첫 번째 코드 패턴을 더 이상 사용하지 않는 것이 좋습니다 . (Java 5 이상을 사용한다고 가정합니다.)


답변

나는 그것을 위해 Reflection을 사용하는 아이디어가 마음에 들지 않습니다.
일부 리팩토링에서 누락되어 위험 할뿐만 아니라 SecurityManager.

FutureTaskjava.util.concurrent 패키지의 다른 옵션과 마찬가지로 좋은 옵션입니다.
내가 가장 좋아하는 간단한 작업 :

    Executors.newSingleThreadExecutor().submit(task);

조금 (작업이 호출 가능 또는의 Runnable입니다) 스레드를 만드는 것보다 짧은 비트


답변

CompletableFuture에 Java8 구문을 사용할 수 있습니다. 이렇게하면 비동기 함수 호출의 결과를 기반으로 추가 비동기 계산을 수행 할 수 있습니다.

예를 들면 :

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

자세한 내용은이 기사 에서 찾을 수 있습니다.


답변

jcabi-aspects 및 AspectJ의 @Async주석을 사용할 수 있습니다 .

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

를 호출 save()하면 새 스레드가 시작되고 본문을 실행합니다. 의 결과를 기다리지 않고 주 스레드가 계속됩니다 save().


답변

이를 위해 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/