자바 내부에서 여러 쓰레드를 생성하여 병렬로 수행해야할 때가 있다.
이 경우 Runnable이나 Thread를 직접 생성하는 경우가 있는데 이럴 필요 없이 java.util.concurrent의 패키지에 있는 코어 기능을 사용하는게 더 편하다.
JDK가 1.5이상이면 사용할 수 있다. 정말 오래된 프로젝트가 아닌 이상.. 있더라도 제네릭을 쓰기위해선 1.5라도 올리는게 좋을 것 같다
testSample = Arrays.asList("가", "나", "다", "라", "마", "바", "사", "후후", "1", "10", "100", "-100");
이 샘플들을 Video라는 객체에 데이터를 넣을 예정이다.
- ExecutorService threadPool = Executors.newFixedThreadPool(4);
4개의 쓰레드를 관리하는 Pool이다.
- List<Future<Video>> futures = new ArrayList<Future<Video>>();
비동기로 수행된 쓰레드의 결과를 담을 목록
- Callable<Video> callable = new Callable<Video>()
반환되는 값은 Video객체를 명시한다.
call 메서드를 통해 처리할 작업을 지정한다. (JDK8 이상이면 익명 클래스가 아닌 람다로 간편히 해결할 수 있다)
- futures.add(threadPool.submit(callable));
submit을 통해 call 메서드를 수행시키고 결과는 Future 목록에 담는다.
- threadPool.shutdown();
작업들이 모두 끝나면 ThreadPool을 종료한다. 자동으로 사라지지 않는다!
get은 앞선 작업들이 완료되면 가져 온다. 그 동안 기다린다.
이 경우 Runnable이나 Thread를 직접 생성하는 경우가 있는데 이럴 필요 없이 java.util.concurrent의 패키지에 있는 코어 기능을 사용하는게 더 편하다.
JDK가 1.5이상이면 사용할 수 있다. 정말 오래된 프로젝트가 아닌 이상.. 있더라도 제네릭을 쓰기위해선 1.5라도 올리는게 좋을 것 같다
Executors, ExecutorService : ThreadPool이라고 생각하면 된다. Callable : Runnable과 유사하지만 Runnable은 return값이 void이고 Callable은 작업할 내용과 리턴 값을 지정할 수 있다. Future : 비동기로 수행한 쓰레드가 수행한 결과를 담는다.
전체 샘플 코드
@Test public void testParallelExecute() throws Exception { List<String> testSample = Arrays.asList("가", "나", "다", "라", "마", "바", "사", "후후", "1", "10", "100", "-100"); // 4개의 Thread를 가진 ThreadPool생성 ExecutorService threadPool = Executors.newFixedThreadPool(4); // Thread들이 비동기로 수행되면 그 결과를 담을 Futrure 객체 List<Future<Video>> futures = new ArrayList<Future<Video>>(); for (final String sample : testSample) { // callable 객체를 통해 어떤 일을 수행할지 결정한다. Callable<Video> callable = new Callable<Video>() { @Override public Video call() throws Exception { System.out.println("Time : "+ new Date() + " -Thread Name : " + Thread.currentThread().getName() + " - Text : " + sample); // 테스트겸 3번만 0.5초간 중지 if (Thread.currentThread().getName().equals("pool-1-thread-3")) { Thread.sleep(50); } Video video = new Video(); video.setDialog(sample); return video; } }; // 생성된 callable들을 threadpool에서 수행시키고 결과는 Future 목록에 담는다. futures.add(threadPool.submit(callable)); } // 수행중인 callable들이 다 끝나면 threadpool을 종료시킨다.(반드시 해야함) // 자동으로 제거되지 않는다. // showdownNow()는 수행중인 callable이 있더라도 인터럽트시켜 강제 종료한다. threadPool.shutdown(); List<Video> results = new ArrayList<Video>(); for (Future<Video> future : futures) { // future에 담긴 결과 객체를 받아 List에 담는다. results.add(future.get()); } // 수행 소비 시간에 상관없이 futures에 담긴 순서대로 출력된다. assertFalse(results.isEmpty()); for (Video result : results) { System.out.println(result.getDialog()); } }- List
이 샘플들을 Video라는 객체에 데이터를 넣을 예정이다.
- ExecutorService threadPool = Executors.newFixedThreadPool(4);
4개의 쓰레드를 관리하는 Pool이다.
- List<Future<Video>> futures = new ArrayList<Future<Video>>();
비동기로 수행된 쓰레드의 결과를 담을 목록
- Callable<Video> callable = new Callable<Video>()
반환되는 값은 Video객체를 명시한다.
call 메서드를 통해 처리할 작업을 지정한다. (JDK8 이상이면 익명 클래스가 아닌 람다로 간편히 해결할 수 있다)
- futures.add(threadPool.submit(callable));
submit을 통해 call 메서드를 수행시키고 결과는 Future 목록에 담는다.
- threadPool.shutdown();
작업들이 모두 끝나면 ThreadPool을 종료한다. 자동으로 사라지지 않는다!
for (Future<Video> future : futures) { // future에 담긴 결과 객체를 받아 List에 담는다. results.add(future.get()); }- Future에 담긴 Video 결과를 꺼내 Video 목록에 담는다.
get은 앞선 작업들이 완료되면 가져 온다. 그 동안 기다린다.
'Java' 카테고리의 다른 글
[Java] 여러 파일을 묶은 하나의 압축파일(Zip) 만들기 (0) | 2018.05.20 |
---|---|
[Json] Jackson을 이용해 추상, 인터페이스 객체 별로 구현체 구분하기 (0) | 2017.12.18 |
모델 클래스에 인터페이스 구현 설계에 대한 내용 (0) | 2016.08.24 |
package javax.crypto does not exist (0) | 2016.08.17 |
MySQL과 Java AES 128 암호/복호 동기화하기 (대칭키, 양방향) (0) | 2016.08.11 |