* 동기와 비동기 개념
- 동기 (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 |