2017년 4월 25일 화요일

ForkJoin

소스:

환경:

gradle, java1.8

개요:

ForkJoin라이브러리를 사용한 예제 구현.

설명:


1. 통상적인 예제는 int 배열의 숫자를 sum하는 것이나 여기서는 String List에서 다른 문장이 있는지 없는지를 체크(다른 아이디가 있는지를 체크)하는 예제로 수정.  

2. 사용법은 RecursiveTask<V>를 상속받아서 compute()를 구현한다.
compute()메소드의 구조는 설정한 SEQUENTIAL_THRESHOLD 이하인 경우는 로직을 수행하고 넘으면 다시 재귀호출을 하고 결과를 리턴한다.
public class ForkJoinSample extends RecursiveTask {

 static final int SEQUENTIAL_THRESHOLD = 500000; // 충분히 작은 단위는 여기서 5로 정했다.
             // 정하기 나름.


 public ForkJoinSample(List arr, int lo, int hi) {
    ....
 }

 @Override
 protected Boolean compute() {
  if (high - low <= SEQUENTIAL_THRESHOLD) { // 충분히 작은 배열 구간이면 값을 계산해 리턴한다.
   boolean result = true;

     // 수행로직...

   return result;

  } else {
   // 배열이 기준보다 크다면 divede and conquer방식으로 적당히 둘이상의 객체로 나누고,
   // 현재 쓰레드에서 처리할 객체는 compute를 호출해 값을 계산하고, fork할 객체는 join하여 값을 기다린후
   // 얻는다.
   int mid = low + (high - low) / 2;

   ForkJoinSample left = new ForkJoinSample(array, low, mid);
   ForkJoinSample right = new ForkJoinSample(array, mid, high);
   left.fork();
   Boolean rightAns = right.compute();
   Boolean leftAns = left.join();

   if (rightAns && leftAns) {
    return true;
   } else {
    return false;
   }
  }
 }
3. pool의 갯수는 commonPool()을 이용하여 자동으로 설정할수 있고 ForkJoinPool생성시 갯수를 지정 할 수 있다.
static Boolean read(List readAllLines) {
  // ForkJoinPool의 시작전과 후의 thread pool size를 비교한다.
  int beforeSize = ForkJoinPool.commonPool().getPoolSize();
  System.out.println("ForkJoin commonPool beforeSize=" + beforeSize);

  // common pool: 자동으로 pool갯수를 정해준다.
  boolean result = ForkJoinPool.commonPool().invoke(
    new ForkJoinSample(readAllLines, 0, readAllLines.size()));

  // custom pool: pool 갯수를 임의로 정할 수 있다.
  // ForkJoinPool myPool = new ForkJoinPool(3);
  // boolean result = myPool.invoke(new ForkJoinSample(readAllLines, 0,
  // readAllLines.size()));

  int afterSize = ForkJoinPool.commonPool().getPoolSize();
  System.out.println("ForkJoin commonPool afterSize=" + afterSize);
  return result;
 }



댓글 없음:

댓글 쓰기