본문 바로가기

공부 정리/Java

자바 비동기

728x90
반응형

 

동기 vs 비동기

 

동기 : 작업들이 한번에 하나씩 이루어지며, 하나의 작업이 끝나고 나서 다음 작업이 시작된다. 

 

비동기 : 하나의 작업이 끝나기 이전에 또다른 작업을 처리할 수 있다. 다양한 요청을 동시에 처리할 수 있으며, 많은 작업을 보다 빠른 시간 내에 끝낼 수 있다.

 

 

자바에서 동시성 사용하기

@Async와 @EnableAsync로 자바 비동기를 구현할 수 있지만, 비동기 메서드와 같은 클래스 내의 다른 메서드에서 비동기 메서드를 호출한다면, AOP proxy를 우회하기 때문에 비동기로 작동하지 않는 것을 유의하여야 한다.

 

보통 비동기처리는 여러개의 API를 동시에 사용하는 경우가 많다. 또한 결과를 이어받아서 처리하거나 결과를 합쳐서 새로운 결과를 내야하는 경우들이 많으므로 CompletableFuture를 통해서 해결한다.

 

자바에서 비동기작업으로 여러작업을 한꺼번에 처리할 수 있으며 이를 동시성(Concurrent) 작업이라고 한다. 자바에서는 멀티프로세싱과 멀티쓰레드를 지원한다. 따라서 비동기처리, 동시성 처리는 쓰레드를 기반으로 한다.

 

Thread 상속

public static void main(String[] args) {
        HelloThread helloThread = new HelloThread();
        helloThread.start();
        System.out.println("hello : " + Thread.currentThread().getName());
    }

static class HelloThread extends Thread {
    @Override
    public void run() {
        System.out.println("world : " + Thread.currentThread().getName());
    }
}

 

Runnable 구현(람다)

Thread thread = new Thread(() -> System.out.println("world : " + Thread.currentThread().getName()));
thread.start();
System.out.println("hello : " + Thread.currentThread().getName());

 

Callable과 Future

*Callable

Runnable과 유사하지만 작업의 결과를 받을 수 있다.

리턴타입은 V이다.

 

Callable<String> hello = () => {
 Thread.sleep(2000L);
 return "hello";
}

 

*Future

비동기적인 작업의 현재 상태를 조회하거나 결과를 가져올 수 있다.

ExecutorService executorService = Executors.newSingleThreadExecutor();

Future<String> helloFuture = executorService.submit(() -> {
    Thread.sleep(2000L);
    return "Callable";
});

System.out.println("Hello");
String result = helloFuture.get(); // 블록킹 콜
System.out.println(result);
executorService.shutdown();

get() 함수는 블록킹 콜이기 때문에 helloFuture.get() 메서드가 다 실행되고 난 이후에 다음 순서를 진행한다.

CompletableFuture

Future를 사용해도 어느정도 처리가 가능하지만, 하기 힘든 일이 많아서 보완으로 나온 기능이다.

Future로는 하기 어렵던 작업들

- Future를 외부에서 완료 시킬 수 없다.

- 여러 Future를 조합할 수 없다

- 예외 처리용 API를 재공하지 않는다.

 

비동기로 작업 실행하기

  • 리턴값이 없는 경우: runAsync()
  • 리턴값이 있는 경우: supplyAsync()

콜백 제공하기

  • thenApply(Function): 리턴값을 받아서 다른 값으로 바꾸는 콜백
  • thenAccept(Consumer): 리턴값을 또 다른 작업을 처리하는 콜백 (리턴없이)
  • thenRun(Runnable): 리턴값 받지 다른 작업을 처리하는 콜백

조합하기

  • thenCompose(): 두 작업이 서로 이어서 실행하도록 조합
  • thenCombine(): 두 작업을 독립적으로 실행하고 둘 다 종료 했을 때 콜백 실행
  • allOf(): 여러 작업을 모두 실행하고 모든 작업 결과에 콜백 실행
  • anyOf(): 여러 작업 중에 가장 빨리 끝난 하나의 결과에 콜백 실행

예외처리

  • exeptionally(Function)
  • handle(BiFunction)

 

출처

https://www.outsystems.com/blog/posts/asynchronous-vs-synchronous-programming/

 

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html

 

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html

728x90
반응형

'공부 정리 > Java' 카테고리의 다른 글

Java 8에서 개선된 가비지 컬렉터는?  (0) 2022.10.19
jar war 차이점  (0) 2022.04.26
RestTemplate  (0) 2021.08.15
Filter vs Interceptor 차이 (Spring)  (0) 2021.08.13
Validation 어노테이션 직접 만들어보기  (0) 2021.08.12