Future는 비동기적인 연산의 결과를 표현하는 클래스입니다. Future를 이용하면 멀티쓰레드 환경에서 처리된 어떤 데이터를 다른 쓰레드에 전달할 수 있습니다.
Future 내부적으로 Thread-Safe 하도록 구현되었기 때문에 synchronized block을 사용하지 않아도 됩니다.
예제를 보면 더 쉽게 이해가 됩니다.
간단한 Future 예제
아래 예제에서는 두개의 Thread가 생성되어있고, Future를 이용하여 어떤 쓰레드에서 처리된 데이터를 다른 쓰레드로 전달합니다.
ExecutorService executor
= Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
System.out.println(LocalTime.now() + " Starting runnable");
Integer sum = 1 + 1;
Thread.sleep(3000);
return sum;
});
System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = future.get();
System.out.println(LocalTime.now() + " Result : " + result);- ExecutorService는 Single Thread를 생성합니다.
submit()으로 Callable을 전달하면, 인자로 전달된 Callable을 수행합니다. - executor.submit()가 호출되었을 때 Future 객체는 리턴됩니다. 하지만 아직 값이 설정되지 않은 상태입니다.
- future.get()는 Future 객체에 어떤 값이 설정될 때까지 기다립니다.
submit()에 전달된 Callable이 어떤 값을 리턴하면 그 값을 Future에 설정합니다.
Callable은 인터페이스로, 인자를 받지 않지만 어떤 데이터를 리턴합니다. Runnable은 인자도 없고 리턴되는 데이터도 없는 인터페이스입니다.
실행 결과는 다음과 같습니다.
01:18:18.347 Starting runnable
01:18:18.347 Waiting the task done
01:18:21.348 Result : 2다른 Future 예제
위의 예제는 간단하지만, Future가 어떻게 생성되고 어떻게 데이터가 저장되는지 보이지 않습니다.
다음 예제를 보시면 이런 부분들을 확인해볼 수 있습니다.
CompletableFuture<Integer> future
= new CompletableFuture<>();
Executors.newCachedThreadPool().submit(() -> {
System.out.println(LocalTime.now() + " Doing something");
Integer sum = 1 + 1;
Thread.sleep(3000);
future.complete(sum);
return null;
});
System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = future.get();
System.out.println(LocalTime.now() + " Result : " + result);- CompletableFuture
으로 Future 객체를 생성합니다. Generics로 구현되어 저장하려는 데이터 타입을 명시합니다. Executors.newCachedThreadPool()는 Thread pool을 생성하며submit()으로 Callable을 전달하면 대기 중인 Thread로부터 실행됩니다.future.complete(data)으로 다른 쓰레드로 전달할 데이터를 저장합니다.future.get()으로 데이터가 set될 때까지 기다립니다.
실행 결과는 다음과 같습니다.
01:23:54.929 Doing something
01:23:54.929 Waiting the task done
01:23:57.930 Result : 2Future.get()에 Timeout 설정
Future에 데이터가 set되지 않으면 Future.get()를 호출한 Thread는 무한히 대기합니다. 그럼 프로그램은 응답없는 상태가 됩니다.
Future.get()에 Timeout을 설정하여 일정 시간 내에 응답이 없으면 리턴하여 다음 작업을 처리하도록 만들 수 있습니다.
Timeout을 설정하려면 아래와 같이 get()에 timeout과 시간 단위인 TimeUnit을 함께 전달하면 됩니다.
Future.get(long timeout, TimeUnit unit)다음은 Timeout을 적용한 예제입니다.
ExecutorService executor
= Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
System.out.println(LocalTime.now() + " Starting runnable");
Integer sum = 1 + 1;
Thread.sleep(4000);
System.out.println(LocalTime.now() + " Exiting runnable");
return sum;
});
System.out.println(LocalTime.now() + " Waiting the task done");
Integer result = null;
try {
result = future.get(2000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
System.out.println(LocalTime.now() + " Timed out");
result = 0;
}
System.out.println(LocalTime.now() + " Result : " + result);get(2000, TimeUnit.MILLISECONDS)는 2000ms를 Timeout으로 설정한다는 의미입니다. TimeUnit을 SECONDS 등으로 변경할 수도 있습니다.- Timeout이 발생하면
TimeoutException예외가 발생합니다.try-catch로 예외처리가 필요합니다.
위 코드의 실행 결과는 다음과 같습니다.
11:55:06.693 Waiting the task done
11:55:06.693 Starting runnable
11:55:08.696 Timed out
11:55:08.696 Result : 0
11:55:10.696 Exiting runnableLoading script...
Related Posts
- Java - Unsupported class file major version 61 에러
- Java - String.matches()로 문자열 패턴 확인 및 다양한 예제 소개
- Java - 문자열 공백제거 (trim, replace)
- Java - replace()와 replaceAll()의 차이점
- Java - ArrayList 초기화, 4가지 방법
- Java - 배열 정렬(Sorting) (오름차순, 내림차순)
- Java - 문자열(String)을 비교하는 방법 (==, equals, compare)
- Java - StringBuilder 사용 방법, 예제
- Java - 로그 출력, 파일 저장 방법 (Logger 라이브러리)
- Java IllegalArgumentException 의미, 발생 이유
- Java - NullPointerException 원인, 해결 방법
- Seleninum의 ConnectionFailedException: Unable to establish websocket connection 해결
- Java - compareTo(), 객체 크기 비교
- Java - BufferedReader로 파일 읽기
- Java - BufferedWriter로 파일 쓰기
- Java - BigInteger 범위, 비교, 연산, 형변환
- Java charAt() 함수 알아보기
- Java contains()로 문자(대소문자 X) 포함 확인
- Java - Set(HashSet)를 배열로 변환
- Java - 문자열 첫번째 문자, 마지막 문자 확인
- Java - 문자열 한글자씩 자르기
- Java - 문자열 단어 개수 가져오기
- Java - 1초마다 반복 실행
- Java - 배열을 Set(HashSet)로 변환
- Java - 여러 Set(HashSet) 합치기
- Java - 명령행 인자 입력 받기
- Java - 리스트 역순으로 순회, 3가지 방법
- Java - 특정 조건으로 리스트 필터링, 3가지 방법
- Java - HashMap 모든 요소들의 합계, 평균 계산
- Java - 특정 조건으로 HashMap 필터링
- Java - 싱글톤(Singleton) 패턴 구현
- Java - 숫자 왼쪽에 0으로 채우기
- Java - String 배열 초기화 방법
- Java - 정렬된 순서로 Map(HashMap) 순회
- Java - HashMap에서 key, value 가져오기