2012-12-28 6 views
2

포크/조그만 예제를 개선하여 Java 포크/조인 프레임 워크 실행 중 도둑질이 발생했다는 것을 보여주고 싶습니다.Java Fork/Join 프레임 워크에서 작업 도용이 발생했다는 것을 어떻게 나타낼 수 있습니까?

다음 코드를 변경하려면 어떻게해야합니까? 예제의 목적 : 여러 스레드 간의 작업 분리를위한 가치있는 선형 연구를 수행하십시오.

package com.stackoverflow.questions; 

import java.util.LinkedList; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.ForkJoinPool; 
import java.util.concurrent.RecursiveTask; 

public class CounterFJ<T extends Comparable<T>> extends RecursiveTask<Integer> { 

    private static final long serialVersionUID = 5075739389907066763L; 
    private List<T> _list; 
    private T _test; 
    private int _lastCount = -1; 
    private int _start; 
    private int _end; 
    private int _divideFactor = 4; 

    private static final int THRESHOLD = 20; 

    public CounterFJ(List<T> list, T test, int start, int end, int factor) { 
     _list = list; 
     _test = test; 
     _start = start; 
     _end = end; 
     _divideFactor = factor; 

    } 

    public CounterFJ(List<T> list, T test, int factor) { 
     this(list, test, 0, list.size(), factor); 
    } 

    @Override 
    protected Integer compute() { 

     if (_end - _start < THRESHOLD) { 
      int count = 0; 
      for (int i = _start; i < _end; i++) { 
       if (_list.get(i).compareTo(_test) == 0) { 
        count++; 
       } 
      } 
      _lastCount = count; 
      return new Integer(count); 
     } 
     LinkedList<CounterFJ<T>> taskList = new LinkedList<>(); 

     int step = (_end - _start)/_divideFactor; 
     for (int j = 0; j < _divideFactor; j++) { 
      CounterFJ<T> task = null; 
      if (j == 0) 
       task = new CounterFJ<T>(_list, _test, _start, _start + step, _divideFactor); 
      else if (j == _divideFactor - 1) 
       task = new CounterFJ<T>(_list, _test, _start + (step * j), _end, _divideFactor); 
      else 
       task = new CounterFJ<T>(_list, _test, _start + (step * j), _start + (step * (j + 1)), _divideFactor); 

      // task.fork(); 
      taskList.add(task); 
     } 
     invokeAll(taskList); 

     _lastCount = 0; 
     for (CounterFJ<T> task : taskList) { 
      _lastCount += task.join(); 
     } 

     return new Integer(_lastCount); 

    } 

    public int getResult() { 
     return _lastCount; 
    } 

    public static void main(String[] args) { 

     LinkedList<Long> list = new LinkedList<Long>(); 
     long range = 200; 
     Random r = new Random(42); 

     for (int i = 0; i < 1000; i++) { 
      list.add(new Long((long) (r.nextDouble() * range))); 
     } 

     CounterFJ<Long> counter = new CounterFJ<>(list, new Long(100), 4); 

     ForkJoinPool pool = new ForkJoinPool(); 
     long time = System.currentTimeMillis(); 
     pool.invoke(counter); 

     System.out.println("Fork join counter in " + (System.currentTimeMillis() - time)); 
     System.out.println("Occurrences:" + counter.getResult()); 

    } 

} 
+2

+1 자신의 문제. – Trying

+0

대단히 감사합니다. – giampaolo

답변

6

마침내 나는 방법을 관리 했으므로 나중에 독자에게 남겨두면 어렵지 않습니다.

RecursiveTask의 비용 생성자에서 인스턴스를 생성했습니다. compute 메서드에서 스레드 실행이 같거나 같은지 확인합니다. 그렇지 않으면 일을 도둑질했습니다.

그래서 나는

private long _threadId = -1; 
private static int stolen_tasks = 0; 

변경된 생성자이 같은이 멤버 변수 추가 :

public CounterFJ(List<T> list, T test, int start, int end, int factor) { 
     _list = list; 
     _threadId = Thread.currentThread().getId(); //added 
     _test = test; 
     _start = start; 
     _end = end; 
     _branchFactor = factor; 
} 

compute 방법으로 비교를 추가 : 해결하기 위해 당신의 노력에 대한

@Override 
    protected Integer compute() { 

     long thisThreadId = Thread.currentThread().getId(); 
     if (_threadId != thisThreadId){ 
      stolen_tasks++; 
     } 
    // rest of the method