class MyMapper<E> { E apply(E v) { ... } }
class MyReducer<E> { E apply(E x, E y) { ... } }
class MapReducer<E> extends CountedCompleter<E> {
final E[] array; final MyMapper<E> mapper;
final MyReducer<E> reducer; final int lo, hi;
MapReducer<E> sibling;
E result;
MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
MyReducer<E> reducer, int lo, int hi) {
super(p);
this.array = array; this.mapper = mapper;
this.reducer = reducer; this.lo = lo; this.hi = hi;
}
public void compute() {
if (hi - lo >= 2) {
int mid = (lo + hi) >>> 1;
MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
left.sibling = right;
right.sibling = left;
setPendingCount(1); // only right is pending
right.fork();
left.compute(); // directly execute left
}
else {
if (hi > lo)
result = mapper.apply(array[lo]);
tryComplete();
}
}
public void onCompletion(CountedCompleter<?> caller) {
if (caller != this) {
MapReducer<E> child = (MapReducer<E>)caller;
MapReducer<E> sib = child.sibling;
if (sib == null || sib.result == null)
result = child.result;
else
result = reducer.apply(child.result, sib.result);
}
}
public E getRawResult() { return result; }
public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
return new MapReducer<E>(null, array, mapper, reducer,
0, array.length).invoke();
}
}
以上是一个CountedCompleter (Java Platform SE 8 )给的一个示例。
1、在进行任务分割的函数compute()中觉得需要注意的点是else逻辑中if(hi > lo)条件满足执行mapper运算。这里的条件个人觉得没有必要吧。因为跳出上面的if(hi - lo >=2)这个判断条件时不应该是(hi - lo >=1)么。既然(hi - lo 已经大于等于1了,hi > lo 还有必要判断吗?)不知道大家怎么看。
2、第2个问题是需要理解onCompletion(CountedCompleter<?> caller)中的if(this != caller)这个判断条件的含义。可以看到在tryComplete()调用中执行CountedCompleter子类覆盖的onCompletion()方法。会发现有s==a==this这种场景,在onCompletion()执行中通过this->a,caller ->s,且this==caller时不能进行reduce归并即oneTask.onCompletion(oneTask)场景过滤掉,只有在parentTask.onCompletion(subTask)这种场景才进行归并。所以我们看到
//当前this任务是caller的父任务。
//归并caller和它的sibling,归并后的结果保证至父任务this的result
MapReducer<E> child = (MapReducer<E>)caller;
MapReducer<E> sib = child.sibling;
if (sib == null || sib.result == null)
result = child.result;
else
result = reducer.apply(child.result, sib.result);
/* 尝试设置完成当前任务 */public final void tryComplete() {
CountedCompleter<?> a = this, s = a;
for (int c;;) {
/* pending 为 0 代表当前没有未完成的任务 */
if ((c = a.pending) == 0) {
/* 默认空实现 */
a.onCompletion(s);
/* 递归父任务,找到顶任务 */
if ((a = (s = a).completer) == null) {
s.quietlyComplete(); // 设置 status 为 NORMAL
return;
}
}
/* CAS 设置 pending - 1 */
else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
return;
}
}