본문 바로가기
Computer Science/JAVA

동기 Async 와 비동기 ASync

by 꽃요미 2024. 11. 18.

* 동기와 비동기 개념

 

 - 동기 (sync) : A라는 작업이 끝나는 동시에 B라는 작업을 시작한다.

public class AsyncExample {
    public static void main(String[] args) {
        /* 작업1 시작 */
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /* 작업1 종료 */
        
        /* 작업2 시작 */
        try {
            Thread.sleep(500);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        /* 작업2 종료 */
    }
}

- 위 코드는 동기코드. 작업1 작업2 연관이 없고, 작업2가 빨리 끝나지만 동기이기 때문에 작업1 끝나고 작업2가 시작됨.

 

 - 비동기 (async) : A라는 작업의 완료 여부와 상관없이 B라는 작업을 시작한다.

public class AsyncExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        
        /* 작업1 */
        executorService.submit(() -> {
            try {
                Thread.sleep(1500);
            } catch (InterruptedExcepteion e) {
                e.printStackTrace();
            }
        });
        
        /* 작업2 */
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        executorService.shutdown();
    }
}

위 코드는 비동기로 바꾼 코드. 

이 경우는 실행 시간이 긴 작업1을 다른 스레드에게 맡기고, 메인 스레드는 밑으로 내려가 작업2를 시작한다.

 

비동기 방식은 작업들이 서로의 작업 시작 및 종료 시간에 영향을 받지 않고, 별도의 작업 시작/종료 시간을 가진다.

모든 비동기 방식은 멀티 스레드에서 작동한다.

 

* 자바에서의 비동기 처리법

 

 1. Callback

  - 다른 주체에게 맡긴 작업이 끝나면 다른 주체 쪽에서 본 주체가 전해 준 콜백 함수를 실행하는 방법.

  * CompletionHandler

   - 비동기 I/O 작업의 결과를 처리하기 위한 목적으로 만들어 졌으며, 콜백 객체를 만드는데 사용된다. completed() 메소드를 오버라이드를 해서 콜백을 구현하고, failed() 메소드를 오버라이드해 작업이 실패했을 때의 처리를 구현함.

 

public class AsyncExample {
    /* CompletionHandler 구현 */
    private static final CompletionHandler<String, Void> completionHandler = new CompletionHandler<>() {
        /* 작업 2 : 작업 1이 성공적으로 종료된 경우 불리는 콜백 */
        @Override
        public void completed(String result, Void attachment) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /* 작업 2 종료 */
        
        /* 작업 1이 실패했을 경우 불리는 콜백 */
        @Override
        public void failed(Throwable exc, Void attachment) {
            System.out.println("작업1 실패: " + exc.toString());
        }
    };
    
    public static void main(String[] args) {
        ExecutorService executorSerive = Executors.newCachedTreadPool();
        
        /* 작업 1 */
        executorService.submit(() -> {
        /* 작업 1 시작 */
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /* 작업 1 종료 */
        String result = "hash";
        if(result.equals("hash")) { // 작업 성공
            completionHandler.completed(result, null);
        } else { // 작업 실패
            completionHandler.failed(new IllegalStateException(), null);
        }
        
    });
    
    /*
    * 별개로 돌아가는 작업 3
    * 작업 3 시작
    */
    try {
        Thread.sleep(1500);
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
    // 작업 3 종료
    }
}

 

작업3 시작 -> 작업 1 시작 -> 작업2 시작 (작업1이 성공하고 completed() 메서드 실행) -> 작업3 종료 -> 작업2 종료

 

  * 함수형 인터페이스

   - 작업1을 마친 뒤 callback으로 받아온 함수형 인터페이스를 실행하는 메소드를 호출함.

   execute()의 인자로 excute()의 작업이 모두 끝난 뒤 실행 될 콜백을 작성했다.

 

2. Future

 - 다른 주체에게 작업을 맡긴 상태에서 본 주체 쪽에서 작업이 끝났는지 직접 확인

 

 * CompletableFuture

 - Future는 다른 주체의 결과를 얻으려면 잠시라도 블로킹 상태에 들어갈 수 밖에 없는 한계가 있어 등장한 CompletableFuture.

'Computer Science > JAVA' 카테고리의 다른 글

디폴트 메서드, 추상 클래스와 인터페이스  (1) 2024.11.20
Java의 실행 엔진  (0) 2024.11.20
Java의 컴파일 과정  (0) 2024.11.20
컬렉션 프레임 워크  (1) 2024.11.20
Class Loader에 대해서  (0) 2024.11.19