public abstract class CountedCompleter<T> extends ForkJoinTask<T>
ForkJoinTaskã§ãã CountedCompleterã¯ãäžè¬ã«ãµãã¿ã¹ã¯ã®åæ¢ããããã¯ãçºçããå Žåã¯ä»ã®åœ¢åŒã®ForkJoinTaskããå
ç¢ã§ãããçŽæçã«ããã°ã©ãã³ã°ãã«ãããªããŸãã CountedCompleterã®äœ¿ç𿹿³ã¯ä»ã®å®äºããŒã¹ã®ã³ã³ããŒãã³ã(CompletionHandlerãªã©)ãšåæ§ã§ãããå®äºã¢ã¯ã·ã§ã³onCompletion(CountedCompleter)ãããªã¬ãŒããããã«ã¯ã1ã€ã§ã¯ãªãè€æ°ã®ä¿çå®äºãå¿
èŠã«ãªãããšããããŸãã å¥ã®æ¹æ³ã§åæåãããå Žåãé€ããä¿çã«ãŠã³ãã¯ãŒãããå§ãŸããŸãããsetPendingCount(int)ãaddToPendingCount(int)ããã³compareAndSetPendingCount(int, int)ã¡ãœããã䜿çšããŠ(ååçã«)倿Žã§ããŸãã tryComplete()ãåŒã³åºãããšãã«ãä¿çã¢ã¯ã·ã§ã³ã®ã«ãŠã³ãããŒãã§ãªãå Žåã¯ãå€ãæžããããŸãããã以å€ã®å Žåã¯ãå®äºã¢ã¯ã·ã§ã³ãå®è¡ããããã®ã³ã³ããªãŒã¿èªäœãã³ã³ããªãŒã¿ãæã£ãŠããå Žåã¯ãã®ã³ã³ããªãŒã¿ã§åŠçãç¶è¡ãããŸãã PhaserãSemaphoreãªã©ã®é¢é£ããåæåã³ã³ããŒãã³ããšåæ§ã«ããããã®ã¡ãœããã¯å
éšã®ã«ãŠã³ãã«ãã圱é¿ãäžããããã以äžã®å
éšç»é²ã確ç«ããŸããã ç¹ã«ãä¿çã¿ã¹ã¯ã®è奿
å ±ã¯ä¿æãããŸããã æ¬¡ã«ç€ºãããã«ãå¿
èŠã«å¿ããŠä¿çã¿ã¹ã¯ãŸãã¯ãããã®çµæã®äžéšãŸãã¯å
šéšãèšé²ãããµãã¯ã©ã¹ãäœæã§ããŸãã æ¬¡ã«ç€ºãããã«ãå®äºã®ãã©ããŒã¹ã®ã«ã¹ã¿ãã€ãºããµããŒããããŠãŒãã£ãªãã£ã»ã¡ãœãããæäŸãããŸãã ãã ããCountedCompleterã¯åºæ¬çãªåæåã¡ã«ããºã ã®ã¿ãæäŸãããããäžé£ã®é¢é£ããçšéã«é©ãããªã³ã¯ããã£ãŒã«ãããã³è¿œå ã®ãµããŒãã»ã¡ãœãããä¿æãããã®ä»ã®æœè±¡ãµãã¯ã©ã¹ãäœæãããšãã«äŸ¿å©ãªå ŽåããããŸãã
å
·è±¡CountedCompleterã¯ã©ã¹ã¯ãã»ãšãã©ã®ã±ãŒã¹ã§(次ã«ç€ºãããã«)埩垰ããåã«tryComplete()ã1ååŒã³åºãcompute()ã¡ãœãããå®çŸ©ããå¿
èŠããããŸãã ãã®ã¯ã©ã¹ã§ã¯ããªãã·ã§ã³ã§ãæ£åžžãªå®äºæã«ã¢ã¯ã·ã§ã³ãå®è¡ããonCompletion(CountedCompleter)ã¡ãœãããšãäŸå€ã®çºçæã«ã¢ã¯ã·ã§ã³ãå®è¡ããonExceptionalCompletion(Throwable, CountedCompleter)ã¡ãœããããªãŒããŒã©ã€ãããããšãã§ããŸãã
ã»ãšãã©ã®å ŽåãCountedCompleterã¯çµæãçæããŸãããéåžžã¯CountedCompleter<Void>ãšããŠå®£èšãããçµæå€ãšããŠåžžã«nullãè¿ããŸãã ãã以å€ã®å Žåã¯ãgetRawResult()ã¡ãœããããªãŒããŒã©ã€ãããŠãjoin()ãinvoke()ããã³é¢é£ã¡ãœããããçµæãæäŸããããã«ããŠãã ããã äžè¬ã«ããã®ã¡ãœããã¯å®äºæã®çµæãä¿æããCountedCompleterãªããžã§ã¯ãã®ãã£ãŒã«ã(ãŸãã¯1ã€ä»¥äžã®ãã£ãŒã«ãã®é¢æ°)ã®å€ãè¿ãå¿
èŠããããŸãã setRawResult(T)ã¡ãœããã¯ãããã©ã«ãã§ã¯CountedCompleterã«äœã®åœ±é¿ãäžããŸããã é©çšå¯èœãªã±ãŒã¹ã¯ã»ãšãã©ãããŸãããããã®ã¡ãœããããªãŒããŒã©ã€ãããŠãçµæããŒã¿ãæã€ä»ã®ãªããžã§ã¯ãããã£ãŒã«ããä¿æããããšãå¯èœã§ãã
ããèªäœã§ã¯ã³ã³ããªãŒã¿ãæããªã(ã€ãŸããgetCompleter()ãnullãè¿ã)CountedCompleterã¯ããã®è¿œå æ©èœãå«ãéåžžã®ForkJoinTaskãšããŠäœ¿çšã§ããŸãã ãã ããå¥ã®ã³ã³ããªãŒã¿ãæã€ã³ã³ããªãŒã¿ã¯ãä»ã®èšç®ã®å
éšãã«ããŒãšããŠã®ã¿æ©èœããããã(ForkJoinTask.isDone()ãªã©ã®ã¡ãœããã§å ±åããã)ããèªäœã®ã¿ã¹ã¯ã»ã¹ããŒã¿ã¹ã¯äžå®ã§ãããã®ã¹ããŒã¿ã¹ã¯ãcomplete(T)ãForkJoinTask.cancel(boolean)ãForkJoinTask.completeExceptionally(Throwable)ã®æç€ºçãªåŒåºãæããŸãã¯computeã¡ãœããã®äŸå€å®äºæã«ã®ã¿å€æŽãããŸãã äŸå€å®äºæã«ãã¿ã¹ã¯ã®ã³ã³ããªãŒã¿(ããã³ãã®ã³ã³ããªãŒã¿ã以äžåæ§)ãååšãããŸã å®äºããŠããªãå Žåã¯ããããã«äŸå€ãäžç¶ãããŸãã åæ§ã«ãå
éšã®CountedCompleterãåãæ¶ããŠãããã®ã³ã³ããªãŒã¿ã«å¯ŸããããŒã«ã«ã®å¹æãããªããããå€ãã®å Žåæå¹ã§ã¯ãããŸããã
䜿çšäŸã
䞊åã®ååž°çåè§£ã CountedCompleterã¯ãRecursiveActionã§äœ¿çšããããã®ãšåæ§ã®ããªãŒã«é
眮ã§ããŸãããã ãããããã®èšå®ã§ã¯éåžžãç°ãªãæ¹æ³ã§æ§ç¯ãè¡ãããŸãã ãã®å Žåãåã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ã¯ãèšç®ããªãŒã§ã¯ã¿ã¹ã¯ã®èŠªã«ãªããŸãã å¿
èŠãªç»é²äœæ¥ãããå€ããªããŸãããé
åãŸãã¯ã³ã¬ã¯ã·ã§ã³ã®åèŠçŽ ã«æéã®ããã(ãã以äžåå²ã§ããªã)ãªãã¬ãŒã·ã§ã³ãé©çšããå Žå(ç¹ã«ãå
¥åºåãªã©ã®åºæã®å·®éãŸãã¯ã¬ããŒãžã»ã³ã¬ã¯ã·ã§ã³ãªã©ã®è£å©å¹æã®ãããããåå ã§ããã®ãªãã¬ãŒã·ã§ã³ã®å®äºã«ãããæéãèŠçŽ ã«ãã£ãŠå€§å¹
ã«ç°ãªãå Žå)ãCountedCompleterã¯ããé©åãªæ¹æ³ã§ããå¯èœæ§ããããŸãã CountedCompleterã¯ç¬èªã®ç¶ç¶ãæäŸãããããä»ã®ã¹ã¬ããã¯CountedCompleterã®å®è¡ã®åŸ
æ©ããããã¯ããå¿
èŠã¯ãããŸããã
ããšãã°ã2åå²ã®ååž°çåè§£ã䜿çšããŠäœæ¥ãåäœ(ãªãŒãã»ã¿ã¹ã¯)ã«åå²ããã¯ã©ã¹ã®åæããŒãžã§ã³ã次ã«ç€ºããŸãã äœæ¥ãåå¥ã®åŒåºãã«åå²ãããŠããå Žåã§ããéåžžã¯ãªãŒãã»ã¿ã¹ã¯ãçŽæ¥ãã©ãŒã¯ãããããã¹ã¬ããééä¿¡ãæžå°ããè² è·åæ£ãåäžããããªãŒããŒã¹ã®ææ³ããèŠãããŸãã ååž°çãªã±ãŒã¹ã§ã¯ãå®äºãããµãã¿ã¹ã¯ã®åãã¢ã®2çªç®ããã®èŠªã®å®äºãããªã¬ãŒããŸã(çµæã®çµåãè¡ãããªããããonCompletionã¡ãœããã®ããã©ã«ãã®ç¡æäœå®è£
ã¯ãªãŒããŒã©ã€ããããŸãã)ã staticãŠãŒãã£ãªãã£ã»ã¡ãœãããããŒã¹ã»ã¿ã¹ã¯ãèšå®ãããããåŒã³åºããŸã(ããã§ã¯ãForkJoinPool.commonPool()ãæé»çã«äœ¿çšããŠããŸã)ã
class MyOperation<E> { void apply(E e) { ... } }
class ForEach<E> extends CountedCompleter<Void> {
public static <E> void forEach(E[] array, MyOperation<E> op) {
new ForEach<E>(null, array, op, 0, array.length).invoke();
}
final E[] array; final MyOperation<E> op; final int lo, hi;
ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
super(p);
this.array = array; this.op = op; this.lo = lo; this.hi = hi;
}
public void compute() { // version 1
if (hi - lo >= 2) {
int mid = (lo + hi) >>> 1;
setPendingCount(2); // must set pending count before fork
new ForEach(this, array, op, mid, hi).fork(); // right child
new ForEach(this, array, op, lo, mid).fork(); // left child
}
else if (hi > lo)
op.apply(array[lo]);
tryComplete();
}
}
ååž°çãªã±ãŒã¹ã§ã¯ãã¿ã¹ã¯ããã®å³åŽã®ã¿ã¹ã¯ããã©ãŒã¯ããåŸã§äœãå®è¡ããªãããã埩垰ããåã«ãã®å·ŠåŽã®ã¿ã¹ã¯ãçŽæ¥åŒã³åºãããšãã§ããç¹ã«æ°ã¥ãããšã§ããã®èšèšãæ¹è¯ã§ããŸãã (ããã¯æ«å°Ÿååž°ã®åé€ã«äŒŒãŠããŸãã) ãŸããã¿ã¹ã¯ã¯(tryCompleteã®åŒåºãã«ãã©ãŒã«ã»ã¹ã«ãŒããã«)ãã®å·ŠåŽã®ã¿ã¹ã¯ã®å®è¡æã«åŸ©åž°ãããããä¿çã«ãŠã³ãã¯1ã«èšå®ãããŸãã
class ForEach<E> ...
public void compute() { // version 2
if (hi - lo >= 2) {
int mid = (lo + hi) >>> 1;
setPendingCount(1); // only one pending
new ForEach(this, array, op, mid, hi).fork(); // right child
new ForEach(this, array, op, lo, mid).compute(); // direct invoke
}
else {
if (hi > lo)
op.apply(array[lo]);
tryComplete();
}
}
ãããªãæ¹è¯ç¹ãšããŠãå·ŠåŽã®ã¿ã¹ã¯ã¯ååšããå¿
èŠããªãããšã«æ³šç®ããŠãã ããã æ°ããã¿ã¹ã¯ãäœæãããããã«ãå
ã®ã¿ã¹ã¯ã䜿çšããŠå埩ããåãã©ãŒã¯ã®ä¿çã«ãŠã³ãã远å ã§ããŸãã ãŸãããã®ããªãŒå
ã®ã¿ã¹ã¯ã¯onCompletion(CountedCompleter)ã¡ãœãããå®è£
ããŠããªããããtryComplete()ãpropagateCompletion()ã«çœ®ãæããããšãã§ããŸãã
class ForEach<E> ...
public void compute() { // version 3
int l = lo, h = hi;
while (h - l >= 2) {
int mid = (l + h) >>> 1;
addToPendingCount(1);
new ForEach(this, array, op, mid, h).fork(); // right child
h = mid;
}
if (h > l)
op.apply(array[l]);
propagateCompletion();
}
ãã®ãããªã¯ã©ã¹ãããã«æ¹è¯ããã«ã¯ãä¿çã«ãŠã³ããã³ã³ã¹ãã©ã¯ã¿ã§èšå®ã§ããããã«äºåèšç®ãããã¯ã©ã¹ããªãŒãã»ã¹ãããçšã«ç¹åãããå埩ããšã«2åã§ã¯ãªãããšãã°4åã«åå²ãããåžžã«åäžã®èŠçŽ ã«åå²ãããããã«é©å¿çãªãããå€ã䜿çšããããªã©ã®å¿
èŠããããŸãã
æ€çŽ¢ã CountedCompleterã®ããªãŒã§ã¯ãããŒã¿æ§é ã®æ§ã
ãªéšåã«å«ãŸããå€ãŸãã¯ããããã£ãæ€çŽ¢ããçµæãèŠã€ãã£ãå Žåã¯ãã ã¡ã«AtomicReferenceã«çµæãå ±åã§ããŸãã ä»ã®ã¿ã¹ã¯ã¯ãã®çµæãããŒãªã³ã°ããŠãäžèŠãªäœæ¥ãåé¿ã§ããŸãã (ããã«ãä»ã®ã¿ã¹ã¯ãåãæ¶ãããšãã§ããŸãããéåžžã¯çµæãèšå®ãããããšããããã«éç¥ãããã®å Žåã¯åŸç¶ã®åŠçãçç¥ãããã®ãããç°¡åã§å¹ççã§ãã) å®å
šãªããŒãã£ã·ã§ã³åã䜿çšããé
åã䜿ã£ãŠå床説æããŸã(ãã®å Žåããå®éã«ã¯ããªãŒãã»ã¿ã¹ã¯ã¯ã»ãšãã©åžžã«è€æ°ã®èŠçŽ ãåŠçããŸã)ã
class Searcher<E> extends CountedCompleter<E> {
final E[] array; final AtomicReference<E> result; final int lo, hi;
Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
super(p);
this.array = array; this.result = result; this.lo = lo; this.hi = hi;
}
public E getRawResult() { return result.get(); }
public void compute() { // similar to ForEach version 3
int l = lo, h = hi;
while (result.get() == null && h >= l) {
if (h - l >= 2) {
int mid = (l + h) >>> 1;
addToPendingCount(1);
new Searcher(this, array, result, mid, h).fork();
h = mid;
}
else {
E x = array[l];
if (matches(x) && result.compareAndSet(null, x))
quietlyCompleteRoot(); // root task is now joinable
break;
}
}
tryComplete(); // normally complete whether or not found
}
boolean matches(E e) { ... } // return true if found
public static <E> E search(E[] array) {
return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
}
}
ãã®äŸã§ã¯ãã«ãŒãã»ã¿ã¹ã¯ãå®äºããã°ãå®äºã管çããããã®ãã以äžã®ç»é²ã¯å¿
èŠãªããããã¿ã¹ã¯ãå
±éã®çµæã«å¯ŸããŠcompareAndSetãå®è¡ãã以å€ã®å¹æãæããªãä»ã®éšåã®ã¿ã§ãªããæ«å°Ÿã®tryCompleteã®ç¡æ¡ä»¶åŒåºããæ¡ä»¶ä»ã(if (result.get() == null) tryComplete();)ã«ããããšãã§ããŸãã
ãµãã¿ã¹ã¯ã®èšé²ã è€æ°ã®ãµãã¿ã¹ã¯ã®çµæãçµåããCountedCompleterã¿ã¹ã¯ã¯ãéåžžãonCompletion(CountedCompleter)ã¡ãœããã§ãããã®çµæã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸãã æ¬¡ã®(ãããã³ã°ãšãªãã¯ã·ã§ã³ã®åããã¹ãŠEã§ããç°¡æåœ¢åŒã®ãããã»ãªãã¥ãŒã¹ãå®è¡ãã)ã¯ã©ã¹ã«ç€ºãããã«ãåå²çµ±æ²»åã®èšèšã§ãããè¡ãæ¹æ³ã®1ã€ã¯ãåãµãã¿ã¹ã¯ã«ãã®å
åŒãèšé²ãããonCompletionã¡ãœããã§ããã«ã¢ã¯ã»ã¹ã§ããããã«ããããšã§ãã ãã®ææ³ã¯ãå·Šãšå³ã®çµæãçµåããé åºãåé¡ã«ãªããªããããªãªãã¯ã·ã§ã³ã«é©çšãããŸããé åºä»ãããããªãã¯ã·ã§ã³ã§ã¯ãå·Šãšå³ãæç€ºçã«æå®ããå¿
èŠããããŸãã åã®äŸã«ç€ºããä»ã®åçåæ¹æ³ã®ããªã¢ã³ããé©çšããããšãã§ããŸãã
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();
}
}
ããã§ãonCompletionã¡ãœããã¯çµæãçµåããå€ãã®å®äºèšèšã«å
±éãã圢åŒãåã£ãŠããŸãã ãã®ã³ãŒã«ããã¯åœ¢åŒã®ã¡ãœããã¯ãä¿çã«ãŠã³ãããŒãã§ãã(ãŸãã¯ãŒãã«ãªã)2ã€ã®ç°ãªãã³ã³ããã¹ãã®ããããã§ãã¿ã¹ã¯ããšã«1åããªã¬ãŒãããŸããã€ãŸãã(1)tryCompleteã®åŒåºãæã«ãã®ä¿çã«ãŠã³ãããŒãã§ããå Žåã¯ããã®ã¿ã¹ã¯èªäœã«ãã£ãŠããªã¬ãŒããã(2)ãã®ãµãã¿ã¹ã¯ã®ãããããå®äºããä¿çã«ãŠã³ãããŒãã«æžããããšãã¯ããã®ãµãã¿ã¹ã¯ã«ãã£ãŠããªã¬ãŒãããŸãã calleråŒæ°ã¯ã±ãŒã¹ãåºå¥ããŸãã ã»ãšãã©ã®å ŽåãåŒåºãåŽãthisã§ããã°ãã¢ã¯ã·ã§ã³ã¯äžèŠã§ãã ãã以å€ã®å ŽåãcalleråŒæ°ã¯çµåãããå€(ãŸãã¯ä»ã®å€ãžã®ãªã³ã¯ããããã¯ãã®äž¡æ¹)ãæäŸããããã«(éåžžã¯ãã£ã¹ããä»ããŠ)䜿çšãããŸãã ä¿çã«ãŠã³ããé©åã«äœ¿çšãããŠããã°ãonCompletionå
ã®ã¢ã¯ã·ã§ã³ã¯ã¿ã¹ã¯ããã³ãã®ãµãã¿ã¹ã¯ã®å®äºæã«(1å)çºçããŸãã ãã®ã¿ã¹ã¯ãŸãã¯ä»ã®å®äºããã¿ã¹ã¯ã®ãã£ãŒã«ããžã®ã¢ã¯ã»ã¹ã®ã¹ã¬ããå®å
šæ§ã確ä¿ããããã«ããã®ã¡ãœããå
ã«åæåã远å ããå¿
èŠã¯ãããŸããã
å®äºã®ãã©ããŒã¹ã onCompletionã䜿çšããŠå®äºãåŠçããããšãäžé©åœãŸãã¯äžéœåã§ããå Žåã¯ãfirstComplete()ããã³nextComplete()ã¡ãœããã䜿çšããŠã«ã¹ã¿ã ã»ãã©ããŒã¹ãäœæã§ããŸãã ããšãã°ã3çªç®ã®ForEachã®äŸã®åœ¢åŒã§å³åŽã®ã¿ã¹ã¯ãåå²ããã®ã¿ã®MapReducerãå®çŸ©ããã«ã¯ã䜿ãæããããŠããªããµãã¿ã¹ã¯ã®ãªã³ã¯ã«æ²¿ã£ãŠå®äºãå調çã«ãªãã¥ãŒã¹ããå¿
èŠããããæ¬¡ã®ããã«è¡ãããšãã§ããŸãã
class MapReducer<E> extends CountedCompleter<E> { // version 2
final E[] array; final MyMapper<E> mapper;
final MyReducer<E> reducer; final int lo, hi;
MapReducer<E> forks, next; // record subtask forks in list
E result;
MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
super(p);
this.array = array; this.mapper = mapper;
this.reducer = reducer; this.lo = lo; this.hi = hi;
this.next = next;
}
public void compute() {
int l = lo, h = hi;
while (h - l >= 2) {
int mid = (l + h) >>> 1;
addToPendingCount(1);
(forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
h = mid;
}
if (h > l)
result = mapper.apply(array[l]);
// process completions by reducing along and advancing subtask links
for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
t.result = reducer.apply(t.result, s.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, null).invoke();
}
}
ããªã¬ãŒã CountedCompleterã®äžã«ã¯ãããèªäœã¯ãã©ãŒã¯ãããªããããããã«ä»ã®èšèšã®æ§æèŠçŽ ã®äžéšãšããŠæ©èœãããã®ããããŸããããã«ã¯ã1ã€ä»¥äžã®éåæã¿ã¹ã¯ã®å®äºãå¥ã®éåæã¿ã¹ã¯ãããªã¬ãŒããCountedCompleterãå«ãŸããŸãã ããšãã°ã
class HeaderBuilder extends CountedCompleter<...> { ... }
class BodyBuilder extends CountedCompleter<...> { ... }
class PacketSender extends CountedCompleter<...> {
PacketSender(...) { super(null, 1); ... } // trigger on second completion
public void compute() { } // never called
public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
}
// sample use:
PacketSender p = new PacketSender();
new HeaderBuilder(p, ...).fork();
new BodyBuilder(p, ...).fork();
| 修食å | ã³ã³ã¹ãã©ã¯ã¿ | 説æ |
|---|---|---|
protected |
CountedCompleter() |
ã³ã³ããªãŒã¿ãæãããåæã®ä¿çã«ãŠã³ãããŒãã§ããæ°ããCountedCompleterãäœæããŸãã
|
protected |
CountedCompleter(CountedCompleter<?> completer) |
æå®ãããã³ã³ããªãŒã¿ãšãä¿çã«ãŠã³ãã®åæå€ãŒãã䜿çšããŠãæ°ããCountedCompleterãäœæããŸãã
|
protected |
CountedCompleter(CountedCompleter<?> completer, int initialPendingCount) |
æå®ãããã³ã³ããªãŒã¿ãšåæä¿çã«ãŠã³ãã䜿çšããŠãæ°ããCountedCompleterãäœæããŸãã
|
| 修食åãšå | ã¡ãœãã | 説æ |
|---|---|---|
void |
addToPendingCount(int delta) |
æå®ãããå€ãä¿çã«ãŠã³ãã«(ååçã«)远å ããŸãã
|
boolean |
compareAndSetPendingCount(int expected, int count) |
ä¿çã«ãŠã³ããæå®ãããäºæ³å€ãçŸåšä¿æããŠããå Žåã«ã®ã¿ãä¿çã«ãŠã³ããæå®ãããã«ãŠã³ãã«(ååçã«)èšå®ããŸãã
|
void |
complete(T rawResult) |
ä¿çã«ãŠã³ãã«é¢ä¿ãªãã
onCompletion(CountedCompleter)ãåŒã³åºãããã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããããã«ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ã«å¯ŸããŠtryComplete()ãããªã¬ãŒããŸã(ååšããå Žå)ã |
abstract void |
compute() |
ãã®ã¿ã¹ã¯ã«ãã£ãŠå®è¡ãããäž»ãªèšç®ã§ãã
|
int |
decrementPendingCountUnlessZero() |
ä¿çã«ãŠã³ãããŒã以å€ã®å Žåã«ãããã(ååçã«)æžåããŸãã
|
protected boolean |
exec() |
CountedCompleterã®å®è¡èŠåãå®è£
ããŸãã
|
CountedCompleter<?> |
firstComplete() |
ãã®ã¿ã¹ã¯ã®ä¿çã«ãŠã³ãããŒãã®å Žåã¯ããã®ã¿ã¹ã¯ãè¿ããŸãããã以å€ã®å Žåã¯ããã®ä¿çã«ãŠã³ããæžåãã
nullãè¿ããŸãã |
CountedCompleter<?> |
getCompleter() |
ãã®ã¿ã¹ã¯ã®ã³ã³ã¹ãã©ã¯ã¿ã§ç¢ºç«ãããã³ã³ããªãŒã¿ãããå Žåã¯ãããè¿ãããªãå Žåã¯
nullãè¿ããŸãã |
int |
getPendingCount() |
çŸåšã®ä¿çã«ãŠã³ããè¿ããŸãã
|
T |
getRawResult() |
èšç®ã®çµæãè¿ããŸãã
|
CountedCompleter<?> |
getRoot() |
çŸåšã®èšç®ã®ã«ãŒããè¿ããŸããã€ãŸãããã®ã¿ã¹ã¯ã«ã³ã³ããªãŒã¿ããªãå Žåã¯ãã®ã¿ã¹ã¯ãè¿ãããã以å€ã®å Žåã¯ãã®ã³ã³ããªãŒã¿ã®ã«ãŒããè¿ããŸãã
|
void |
helpComplete(int maxTasks) |
ãã®ã¿ã¹ã¯ãå®äºããŠããªãå Žåã«ããã®ã¿ã¹ã¯ããã®å®äºãã¹ã«å«ãŸããä»ã®æªåŠçã¿ã¹ã¯ã®åŠçããæå®ãããæ°ãé床ã«è©Šè¡ããŸã(ãã®ãããªã¿ã¹ã¯ãååšããããšãããã£ãŠããå Žå)ã
|
CountedCompleter<?> |
nextComplete() |
ãã®ã¿ã¹ã¯ã«ã³ã³ããªãŒã¿ããªãå Žåã¯ã
ForkJoinTask.quietlyComplete()ãåŒã³åºããnullãè¿ããŸãã |
void |
onCompletion(CountedCompleter<?> caller) |
ã¡ãœãã
tryComplete()ãåŒã³åºããããšãã«ä¿çã«ãŠã³ãããŒãã®å ŽåããŸãã¯ç¡æ¡ä»¶ã¡ãœããcomplete(T)ãåŒã³åºãããå Žåãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã |
boolean |
onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) |
ã¡ãœãã
ForkJoinTask.completeExceptionally(Throwable)ãåŒã³åºããããã¡ãœããcompute()ãäŸå€ãã¹ããŒãããšãã«ããã®ã¿ã¹ã¯ããŸã æ£åžžã«å®äºããŠããªãå Žåãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã |
void |
propagateCompletion() |
tryComplete()ãšåçã§ãããå®äºãã¹ã«æ²¿ã£ãŠonCompletion(CountedCompleter)ãåŒã³åºããŸãããä¿çã«ãŠã³ãããŒã以å€ã®å Žåã¯ãã«ãŠã³ããæžåããŸããããã§ãªãå Žåã¯ãåæ§ã«ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãå®äºããããšããã³ã³ããªãŒã¿ãååšããªãå Žåã¯ãã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããŸãã |
void |
quietlyCompleteRoot() |
getRoot().quietlyComplete()ãšåçã§ãã |
void |
setPendingCount(int count) |
ä¿çã«ãŠã³ããæå®ãããå€ã«èšå®ããŸãã
|
protected void |
setRawResult(T t) |
çµæãçæããCountedCompleterãçµæããŒã¿ãä¿æããããã«ãªãã·ã§ã³ã§äœ¿çšããã¡ãœããã§ãã
|
void |
tryComplete() |
ä¿çã«ãŠã³ãããŒãã§ãªãå Žåã¯ããã®ã«ãŠã³ããæžãããŸãããã以å€ã®å Žåã¯ã
onCompletion(CountedCompleter)ãåŒã³åºããåŸããã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãååšããå Žåã¯ãåæ§ã«ãã®å®è¡ã詊ã¿ãååšããªãå Žåã¯ããã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããŸãã |
adapt, adapt, adapt, cancel, compareAndSetForkJoinTaskTag, completeExceptionally, fork, get, get, getException, getForkJoinTaskTag, getPool, getQueuedTaskCount, getSurplusQueuedTaskCount, helpQuiesce, inForkJoinPool, invoke, invokeAll, invokeAll, invokeAll, isCancelled, isCompletedAbnormally, isCompletedNormally, isDone, join, peekNextLocalTask, pollNextLocalTask, pollTask, quietlyComplete, quietlyInvoke, quietlyJoin, reinitialize, setForkJoinTaskTag, tryUnforkprotected CountedCompleter(CountedCompleter<?> completer, int initialPendingCount)
completer - ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãååšããªãå Žåã¯nullinitialPendingCount - åæã®ä¿çã«ãŠã³ãprotected CountedCompleter(CountedCompleter<?> completer)
completer - ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãååšããªãå Žåã¯nullprotected CountedCompleter()
public abstract void compute()
public void onCompletion(CountedCompleter<?> caller)
tryComplete()ãåŒã³åºããããšãã«ä¿çã«ãŠã³ãããŒãã®å ŽåããŸãã¯ç¡æ¡ä»¶ã¡ãœããcomplete(T)ãåŒã³åºãããå Žåãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã ããã©ã«ãã§ã¯ããã®ã¡ãœããã¯äœãè¡ããŸããã æå®ãããåŒåºãåŽåŒæ°ã®è奿
å ±ã確èªããããšã§ãã±ãŒã¹ãåºå¥ã§ããŸãã thisãšçãããªãå Žåã¯ãéåžžãçµåããçµæ(ãŸãã¯ä»ã®çµæãžã®ãªã³ã¯ããããã¯ãã®äž¡æ¹)ãå«ãå¯èœæ§ããããµãã¿ã¹ã¯ã§ãã caller - ãã®ã¡ãœãããåŒã³åºããŠããã¿ã¹ã¯(ãã®ã¿ã¹ã¯èªäœã§ããå Žåããã)public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller)
ForkJoinTask.completeExceptionally(Throwable)ãåŒã³åºããããã¡ãœããcompute()ãäŸå€ãã¹ããŒãããšãã«ããã®ã¿ã¹ã¯ããŸã æ£åžžã«å®äºããŠããªãå Žåãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã ãã®ã¡ãœããã«å
¥ã£ããšãã¯ããã®ã¿ã¹ã¯ã¯ForkJoinTask.isCompletedAbnormally() (ç°åžžãªç¶æ
ã§ã®å®äº)ã«ãªããŸãã ãã®ã¡ãœããã®æ»ãå€ã¯ããããªãäŒæãå·Šå³ããŸããæ»ãå€ãtrueã§ããã®ã¿ã¹ã¯ãå®äºããŠããªãã³ã³ããªãŒã¿ãæã£ãŠããå Žåã¯ããã®ã³ã³ããªãŒã¿ããã®ã³ã³ããªãŒã¿ãšåãäŸå€ã§å®äºããŸãã ãã®ã¡ãœããã®ããã©ã«ãå®è£
ã¯ãtrueãè¿ã以å€äœãããŸããã ex - äŸå€caller - ãã®ã¡ãœãããåŒã³åºããŠããã¿ã¹ã¯(ãã®ã¿ã¹ã¯èªäœã§ããå Žåããã)trueãpublic final CountedCompleter<?> getCompleter()
nullãè¿ããŸããpublic final int getPendingCount()
public final void setPendingCount(int count)
count - ã«ãŠã³ãpublic final void addToPendingCount(int delta)
delta - 远å ããå€public final boolean compareAndSetPendingCount(int expected,
int count)
expected - äºæ³å€count - æ°ããå€truepublic final int decrementPendingCountUnlessZero()
public final CountedCompleter<?> getRoot()
public final void tryComplete()
onCompletion(CountedCompleter)ãåŒã³åºããåŸããã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãååšããå Žåã¯ãåæ§ã«ãã®å®è¡ã詊ã¿ãååšããªãå Žåã¯ããã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããŸããpublic final void propagateCompletion()
tryComplete()ãšåçã§ãããå®äºãã¹ã«æ²¿ã£ãŠonCompletion(CountedCompleter)ãåŒã³åºããŸãããä¿çã«ãŠã³ãããŒã以å€ã®å Žåã¯ãã«ãŠã³ããæžåããŸããããã§ãªãå Žåã¯ãåæ§ã«ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ãå®äºããããšããã³ã³ããªãŒã¿ãååšããªãå Žåã¯ãã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããŸãã ãã®ã¡ãœããã¯ãèšç®å
ã®åã³ã³ããªãŒã¿ã«å¯ŸããŠonCompletionãåŒã³åºãããšãã§ããªã(ãŸãã¯å¿
èŠã§ãªã)å Žåã«åœ¹ç«ã€ããšããããŸãã public void complete(T rawResult)
onCompletion(CountedCompleter)ãåŒã³åºãããã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããããã«ãã®ã¿ã¹ã¯ã®ã³ã³ããªãŒã¿ã«å¯ŸããŠtryComplete()ãããªã¬ãŒããŸã(ååšããå Žå)ã æå®ãããrawResultã¯ãonCompletion(CountedCompleter)ãåŒã³åºããããŸãã¯ãã®ã¿ã¹ã¯ãå®äºãããã®ãšããŠããŒã¯ããåã«ãsetRawResult(T)ãžã®åŒæ°ãšããŠäœ¿çšãããŸãããã®å€ã¯ãsetRawResultããªãŒããŒã©ã€ãããã¯ã©ã¹ã§ã®ã¿æå¹ã§ãã ãã®ã¡ãœããã¯ä¿çã«ãŠã³ãã倿ŽããŸããã
ãã®ã¡ãœããã¯ãè€æ°ã®ãµãã¿ã¹ã¯ã®çµæã®(ãã¹ãŠã§ã¯ãªã)ãããããååŸãããçŽåŸã«åŒ·å¶çã«å®äºããå Žåã«åœ¹ç«ã€ããšããããŸãã ãã ããsetRawResultããªãŒããŒã©ã€ãããªãäžè¬çãª(ãã€æšå¥šããã)ã±ãŒã¹ã§ã¯ãquietlyCompleteRoot();ã䜿çšããŠãã®å¹æãããç°¡åã«åŸãããšãã§ããŸãã
completeãã¯ã©ã¹ForkJoinTask<T>rawResult - çã®çµæpublic final CountedCompleter<?> firstComplete()
nullãè¿ããŸãã ãã®ã¡ãœããã¯ãå®äºãã©ããŒã¹ã»ã«ãŒãã§nextComplete()ãšãšãã«äœ¿çšããããã«èšèšãããŠããŸãã nullpublic final CountedCompleter<?> nextComplete()
ForkJoinTask.quietlyComplete()ãåŒã³åºããnullãè¿ããŸãã ãŸãã¯ãã³ã³ããªãŒã¿ã®ä¿çã«ãŠã³ãããŒã以å€ã®å Žåã¯ããã®ä¿çã«ãŠã³ããæžåããnullãè¿ããŸãã ãã以å€ã®å Žåã¯ãã³ã³ããªãŒã¿ãè¿ããŸãã ãã®ã¡ãœããã¯ãåçš®é¡ã®ã¿ã¹ã¯éå±€ã«å¯Ÿããå®äºãã©ããŒã¹ã»ã«ãŒãã®äžéšãšããŠäœ¿çšã§ããŸãã
for (CountedCompleter<?> c = firstComplete();
c != null;
c = c.nextComplete()) {
// ... process c ...
}nullpublic final void quietlyCompleteRoot()
getRoot().quietlyComplete()ãšåçã§ããpublic final void helpComplete(int maxTasks)
maxTasks - åŠçããã¿ã¹ã¯ã®æå€§æ°ã ãŒããŸãã¯ããããå°ããå Žåãã¿ã¹ã¯ã¯åŠçãããªãã protected final boolean exec()
execãã¯ã©ã¹ForkJoinTask<T>truepublic T getRawResult()
nullãè¿ããŸããããã¯ãVoidã¢ã¯ã·ã§ã³ã®å Žåã¯é©åã§ããããã以å€ã®å Žåã¯ãªãŒããŒã©ã€ãããŠãã»ãšãã©åžžã«å®äºæã®çµæãä¿æãããã£ãŒã«ããŸãã¯ãã£ãŒã«ãã®é¢æ°ãè¿ãå¿
èŠããããŸãã getRawResultãã¯ã©ã¹ForkJoinTask<T>protected void setRawResult(T t)
setRawResultãã¯ã©ã¹ForkJoinTask<T>t - å€ ãã°ãŸãã¯æ©èœãéä¿¡
詳现ãªAPIãªãã¡ã¬ã³ã¹ããã³éçºè
ããã¥ã¡ã³ãã«ã€ããŠã¯ãJava SEã®ããã¥ã¡ã³ããåç
§ããŠãã ããã ãã®ããã¥ã¡ã³ãã«ã¯ãæŠå¿µçãªæŠèŠãçšèªã®å®çŸ©ãåé¿æ¹æ³ãæå¹ãªã³ãŒãäŸãªã©ã®ãéçºè
ã察象ã«ãããã詳现ãªèª¬æãå«ãŸããŠããŸãã
Copyright © 1993, 2025, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. Documentation Redistribution Policyãåç
§ããŠãã ããã