Á˽â
Java 8 ¹¦ÄÜÈçºÎÈò¢·¢ÐÔ±à³Ì±äµÃ¸üÈÝÒ×
Java? 8 °üº¬ÐµÄÓïÑÔ¹¦ÄÜ£¬Ìí¼ÓÁËÈñà³Ì±äµÃ¸ü¼Ó¼ò±ãµÄÀ࣬°üÀ¨²¢·¢ÐÔ±à³Ì¡£Á˽â
Java 8 À©Õ¹ÌṩµÄȫеġ¢¹¦ÄÜÇ¿´óµÄ²¢Ðд¦ÀíÓïÑÔÖ§³Ö£¬ÆäÖаüÀ¨ CompletableFuture
ºÍÁ÷¡£Äú¿ÉÒÔ¿´µ½£¬ÕâЩй¦ÄÜÓ뱾ϵÁÐµÄ ÊׯªÎÄÕ ÖÐ̽ÌÖµÄijЩ Scala ¹¦ÄÜÓÐÏàËÆÖ®´¦¡£
ÔÚÆÚ´ýÒÑ¾ÃµÄ Java 8 °æ±¾ÖУ¬²¢·¢ÐÔ·½ÃæÒÑʵÏÖÁËÐí¶à¸Ä½ø£¬ÆäÖаüÀ¨ÔÚ
java.util.concurrent ²ã¼¶ÖÐÔö¼ÓеÄÀàºÍÇ¿´óµÄв¢ÐÐÁ÷ ¹¦ÄÜ¡£Éè¼ÆÁ÷µÄÄ¿µÄÊÇÓë lambda
±í´ïʽ ¹²Í¬Ê¹Óã¬Java 8 µÄÕâÏîÔöǿҲʹµÃÈÕ³£±à³ÌµÄÆäËûºÜ¶à·½Ãæ±äµÃ¸ü¼Ó¼ò±ã¡££¨²Î¼û½éÉÜ Java
8 ÓïÑÔµÄ Ö¸ÄÏÎÄÕ£¬Á˽â¶ÔÓÚ lambda ±í´ïʽµÄ½éÉܼ°Ïà¹Ø interface ¸Ä¶¯¡££©
±¾ÎÄÊ×ÏȽéÉÜÁËÐ嵀 CompletableFuture ÀàÈçºÎ¸üºÃµØÐµ÷Òì²½²Ù×÷¡£½ÓÏÂÀ´£¬ÎÒ½«½éÉÜÈçºÎʹÓò¢ÐÐÁ÷£¨Java
8 ÖÐÔÚ²¢·¢ÐÔ·½Ãæ×î´óµÄÁÁµã£©ÔÚÖµ¼¯Éϲ¢ÐеØÖ´ÐвÙ×÷¡£×îºó£¬ÎÒ̽ÌÖÁË Java 8 й¦ÄܵÄÖ´Ðз½·¨£¬²¢Óë´ËϵÁÐ
ÊׯªÎÄÕ ÖеÄһЩ´úÂë½øÐÐÁ˱Ƚϡ££¨²Î¼û ²Î¿¼×ÊÁÏ Öеı¾ÎÄÍêÕûʾÀý´úÂëµÄÁ´½Ó¡££©
»Øµ½ Future
´ËϵÁÐÖÐµÄ ÊׯªÎÄÕ ¼òÒª½éÉÜÁË Java ºÍ Scala Future¡£Java
8 ֮ǰµÄ Java °æ±¾¹¦ÄܽÏÈõ£¬½öÖ§³ÖÁ½ÖÖÓ÷¨£ºÒªÃ´¼ì²é future ÊÇ·ñÒѾÍê³É£¬ÒªÃ´µÈ´ý future
Íê³É¡£Scala °æ±¾ÒªÁé»îµÃ¶à£º¿ÉÒÔÔÚ future Íê³ÉʱִÐлص÷º¯Êý£¬²¢ÒÔ Throwable µÄÐÎʽ´¦ÀíÒì³£µÄÍê³É¡£
Java 8 Ôö¼ÓÁË CompletableFuture<T> À࣬ËüʵÏÖÁËÐ嵀 CompletionStage<T>
½Ó¿Ú£¬²¢¶Ô Future<T> ½øÐÐÁËÀ©Õ¹¡££¨±¾½ÚÖÐÌÖÂÛµÄËùÓв¢·¢ÐÔÀàÓë½Ó¿ÚÈ«¶¼°üº¬ÔÚ java.util.concurrent
°üÖС££©CompletionStage ´ú±íÒì²½¼ÆËãÖеÄÒ»¸ö½×¶Î»ò²½Öè¡£¸Ã½Ó¿Ú¶¨ÒåÁ˶àÖÖ²»Í¬µÄ·½Ê½£¬½«
CompletionStage ʵÀýÓëÆäËûʵÀý»ò´úÂëÁ´½ÓÔÚÒ»Æð£¬±ÈÈçÍê³Éʱµ÷Óõķ½·¨£¨Ò»¹² 59 ÖÖ·½·¨£¬±È
Future ½Ó¿ÚÖÐµÄ 5 ÖÖ·½·¨Òª¶àµÃ¶à¡££©
Çåµ¥ 1 ÏÔʾÁË ChunkDistanceChecker À࣬Ëü»ùÓÚ
ÊׯªÎÄÕ Öеı༾àÀë±È½Ï´úÂë¡£
Çåµ¥ 1. ChunkDistanceChecker
public class ChunkDistanceChecker { private final String[] knownWords;
public ChunkDistanceChecker(String[] knowns)
{
knownWords = knowns;
}
/**
* Build list of checkers spanning word list.
*
* @param words
* @param block
* @return checkers
*/
public static List<ChunkDistanceChecker>
buildCheckers(String[] words, int block) {
List<ChunkDistanceChecker> checkers = new
ArrayList<>();
for (int base = 0; base < words.length; base
+= block) {
int length = Math.min(block, words.length - base);
checkers.add(new ChunkDistanceChecker(Arrays.copyOfRange(words,
base, base + length)));
}
return checkers;
}
...
/**
* Find best distance from target to any known
word.
*
* @param target
* @return best
*/
public DistancePair bestDistance(String target)
{
int[] v0 = new int[target.length() + 1];
int[] v1 = new int[target.length() + 1];
int bestIndex = -1;
int bestDistance = Integer.MAX_VALUE;
boolean single = false;
for (int i = 0; i < knownWords.length; i++)
{
int distance = editDistance(target, knownWords[i],
v0, v1);
if (bestDistance > distance) {
bestDistance = distance;
bestIndex = i;
single = true;
} else if (bestDistance == distance) {
single = false;
}
}
return single ? new DistancePair(bestDistance,
knownWords[bestIndex]) :
new DistancePair(bestDistance);
}
} |
ChunkDistanceChecker ÀàµÄÿ¸öʵÀý¸ºÔð¸ù¾ÝÒ»¸öÒÑÖªµ¥´ÊÊý×éÀ´¼ì²éÄ¿±êµ¥´Ê£¬´Ó¶øÕÒ³ö×î¼ÑÆ¥Åä¡£¾²Ì¬µÄ
buildCheckers() ·½·¨´ÓÕû¸öÒÑÖªµ¥´ÊÊý×é´´½¨Ò»¸ö List<ChunkDistanceChecker>
ºÍÒ»¸öºÏÊʵĿé´óС¡£Õâ¸ö ChunkDistanceChecker ÀàÊDZ¾ÎÄÖм¸ÖÖ²¢·¢ÊµÏֵĻù´¡£¬µÚÒ»ÖÖʵÏÖ¾ÍÊÇÇåµ¥
2 ÖÐµÄ CompletableFutureDistance0 Àà¡£
Çåµ¥ 2. ʹÓà CompletableFuture µÄ±à¼¾àÀë¼ÆËã
public class CompletableFutureDistance0 extends TimingTestBase { private final List<ChunkDistanceChecker> chunkCheckers;
private final int blockSize;
public CompletableFutureDistance0(String[] words,
int block) {
blockSize = block;
chunkCheckers = ChunkDistanceChecker.buildCheckers(words,
block);
}
...
public DistancePair bestMatch(String target) {
List<CompletableFuture<DistancePair>>
futures = new ArrayList<>();
for (ChunkDistanceChecker checker: chunkCheckers)
{
CompletableFuture<DistancePair> future =
CompletableFuture.supplyAsync(() -> checker.bestDistance(target));
futures.add(future);
}
DistancePair best = DistancePair.worstMatch();
for (CompletableFuture<DistancePair> future:
futures) {
best = DistancePair.best(best, future.join());
}
return best;
}
} |
Çåµ¥ 2 CompletableFutureDistance0 ÀàÏÔʾÁËʹÓÃ
CompletableFuture ½øÐв¢·¢¼ÆËãµÄÒ»ÖÖ·½Ê½¡£supplyAsync() ·½·¨Ê¹ÓÃÒ»¸ö Supplier<T>
ʵÀý£¨Ò»¸ö´øÓзµ»Ø T ÀàÐÍÖµµÄ·½·¨µÄº¯Êýʽ½Ó¿Ú£©£¬²¢ÔÚ¶Ô Supplier ½øÐÐÅŶÓÒÔ±ãÒì²½ÔËÐÐËüʱ·µ»Ø
CompletableFuture<T>¡£ÎÒÏòµÚÒ»¸ö for Ñ»·ÖÐµÄ supplyAsync()
·½·¨´«µÝÁËÒ»¸ö lambda ±í´ïʽ£¬Ä¿µÄÊǹ¹½¨Ò»¸öÓë ChunkDistanceChecker Êý×éÏàÆ¥ÅäµÄ
future ÁÐ±í¡£µÚ¶þ¸ö for Ñ»·µÈ´ýÿ¸ö future Íê³É£¨µ«´ó¶àÊý»áÔÚÑ»·µ½´ï֮ǰÍê³É£¬ÒòΪËüÃÇÊÇÒì²½Ö´Ðеģ©£¬È»ºó´ÓËùÓнá¹ûÖÐÊÕ¼¯×î¼ÑÆ¥Åä¡£
ÔÚ CompletableFuture ÉϽøÐй¹½¨
ÔÚ±¾ÏµÁÐµÄ ÊׯªÎÄÕ ÖÐÄúÒѾ¿´µ½£¬Ê¹Óà Scala Future ¿ÉÒÔͨ¹ý¸÷ÖÖ·½Ê½¸½¼ÓÍê³É´¦Àí³ÌÐòºÍ×éºÏ
future¡£CompletableFuture Ϊ Java 8 ÌṩÁËÀàËÆµÄÁé»îÐÔ¡£ÔÚÕâһС½ÚÖУ¬Äú½«Ôڱ༾àÀë¼ì²éµÄÉÏÏÂÎÄÖÐѧϰʹÓÃÕâЩ¹¦ÄܵÄһЩ·½Ê½¡£
Çåµ¥ 3 ÏÔʾÁË Çåµ¥ 2 ÖÐ bestMatch() ·½·¨µÄÁíÒ»¸ö°æ±¾¡£¸Ã°æ±¾Ê¹ÓÃÒ»¸ö´ø
CompletableFuture µÄÍê³É´¦Àí³ÌÐò£¬ÒÔ¼°Ò»Ð©½ÏÀϵIJ¢·¢ÐÔÀà¡£
Çåµ¥ 3. Íê³É´¦Àí³ÌÐòµÄ CompletableFuture
public DistancePair bestMatch(String target) { AtomicReference<DistancePair> best = new AtomicReference<>(DistancePair.worstMatch()); CountDownLatch latch = new CountDownLatch(chunkCheckers.size()); for (ChunkDistanceChecker checker: chunkCheckers) { CompletableFuture.supplyAsync(() -> checker.bestDistance(target)) .thenAccept(result -> { best.accumulateAndGet(result, DistancePair::best); latch.countDown(); }); } try { latch.await(); } catch (InterruptedException e) { throw new RuntimeException("Interrupted during calculations", e); } return best.get(); } |
ÔÚ Çåµ¥ 3 ÖУ¬CountDownLatch ±»³õʼ»¯Îª´úÂëÖд´½¨µÄ
futures µÄÊýÁ¿¡£´´½¨Ã¿¸ö future ʱ£¬ÎÒʹÓà CompletableFuture.thenAccept()
·½·¨¸½¼ÓÁËÒ»¸ö´¦ÀíÆ÷£¨ÒÔ java.util.function.Consumer<T> º¯Êýʽ½Ó¿ÚµÄÒ»¸ö
lambda ʵÀýµÄÐÎʽ£©¡£¸Ã´¦ÀíÆ÷ÔÚ future Õý³£Íê³ÉʱִÐУ¬ËüʹÓà AtomicReference.accumulateAndGet()
·½·¨£¨Java 8 ÖÐÔö¼ÓµÄ£©À´¸üÐÂÕÒµ½µÄ×î¼ÑÖµ£¬È»ºó½«ãÅËø (latch) µÝ¼õ¡£Óë´Ëͬʱ£¬Ö´ÐеÄÖ÷Ï߳̽øÈëÁË
try-catch ¿é£¬²¢µÈ´ýãÅËøÊÍ·Å¡£µ±ËùÓÐ futures Íê³Éºó£¬Ö÷Ï̻߳á¼ÌÐø£¬È»ºó·µ»ØÕÒµ½µÄ×îºóÒ»¸ö×î¼ÑÖµ¡£
Çåµ¥ 4 ÏÔʾÁË Çåµ¥ 2 ÖÐ bestMatch() ·½·¨µÄÁíÒ»¸ö°æ±¾¡£
Çåµ¥ 4. ×éºÏʹÓà CompletableFuture
public DistancePair bestMatch(String target) { CompletableFuture<DistancePair> last = CompletableFuture.supplyAsync(bestDistanceLambda(0, target)); for (int i = 1; i < chunkCheckers.size(); i++) { last = CompletableFuture.supplyAsync(bestDistanceLambda(i, target)) .thenCombine(last, DistancePair::best); } return last.join(); }
private Supplier<DistancePair> bestDistanceLambda(int
i, String target) {
return () -> chunkCheckers.get(i).bestDistance(target);
} |
Õâ¶Î´úÂëʹÓÃÁË CompletableFuture.thenCombine
() ·½·¨½«Á½¸ö future ºÏ²¢£¬¾ßÌå×ö·¨ÊǶÔÁ½¸ö½á¹ûʹÓÃÒ»¸ö java.util.function.BiFunction
·½·¨£¨ÔÚÕâ¸öÀý×ÓÖÐΪ DistancePair.best() ·½·¨£©£¬È»ºó·µ»ØÒ»¸ö future ×÷Ϊº¯ÊýµÄ½á¹û¡£
Çåµ¥ 4 ÊÇ×î¼ò½àºÍ×î¸É¾»µÄ´úÂë°æ±¾£¬µ«ËüÓÐÒ»¸öȱµã£¬¾ÍÊÇ´´½¨ÁËÒ»¸ö¶îÍâµÄ
CompletableFuture ²ãÀ´±íʾÿ´ÎÅúÁ¿²Ù×÷Óë֮ǰ²Ù×÷µÄ×éºÏʹÓá£×÷Ϊ×î³õµÄ Java 8
°æ±¾£¬ÕâÓпÉÄܵ¼Ö StackOverflowException£¨ÔÚ´Ë´úÂëÖÐδ°üº¬¸ÃÒì³££©£¬´Ó¶øµ¼ÖÂ×îºóÒ»¸ö
future ÓÀÔ¶ÎÞ·¨Íê³É¡£Õâ¸ö bug ÕýÔÚ±»½â¾ö£¬ÔÚ½üÆÚµÄ°æ±¾ÖлáµÃµ½ÐÞÕý¡£
CompletableFuture ¶¨ÒåÁËÕâЩÀý×ÓÖÐËùÓ÷½·¨µÄ¶à¸ö±äÌå¡£µ±Äú¶ÔÄúµÄÓ¦ÓóÌÐòʹÓÃ
CompletableFuture ʱ£¬¿ÉÒÔ¼ì²éÍê³É·½·¨µÄÍêÕûÁÐ±í£¬È»ºó½áºÏʹÓöàÖÖ·½·¨À´ÕÒ³öÄúÐèÒªµÄ×î¼ÑÆ¥Åä¡£
µ±ÄúÖ´Ðи÷ÖÖÀàÐ͵IJÙ×÷²¢ÇÒ±ØÐëµ÷Õû½á¹ûʱ£¬CompletableFuture
ÊÇ×î¼ÑÑ¡Ôñ¡£µ±Ôںܶ಻ͬµÄÊý¾ÝÖµÉÏÔËÐÐÏàͬ¼ÆËã¹ý³Ìʱ£¬²¢ÐÐÁ÷½«ÎªÄúÌṩһ¸ö¸ü¼òµ¥µÄ·½·¨ºÍ¸üºÃµÄÐÔÄÜ¡£±à¼¾àÀë¼ì²éµÄÀý×Ó¸üÊʺϲ¢ÐÐÁ÷·½·¨¡£
Á÷
Á÷ÊÇ Java 8 µÄÖ÷ÒªÌØÉ«Ö®Ò»£¬¿ÉÓë lambda ±í´ïʽ½áºÏʹÓᣴӸù±¾ÉϽ²£¬Á÷¾ÍÊÇ»ùÓÚÒ»¸öÖµÐòÁеÄÍÆË͵ü´úÆ÷¡£Á÷¿ÉÒÔÓëÊÊÅäÆ÷Á´½ÓÔÚÒ»Æð£¬ÒÔ±ãÖ´ÐÐÖîÈç¹ýÂËÓëÓ³ÉäÖ®ÀàµÄ²Ù×÷£¬ÕâÒ»µãÓë
Scala ÐòÁкÜÏñ¡£Á÷»¹Óд®ÐкͲ¢ÐеıäÌ壬ÕâÒ²ºÍ Scala ÐòÁкÜÏñ£¨µ« Scala ÓÐÒ»¸öÓÃÓÚ²¢ÐÐÐòÁеĵ¥¶ÀµÄÀà²ã¼¶£¬¶ø
Java 8 ʹÓÃÒ»¸öÄÚ²¿±ê¼ÇÀ´Ö¸Ê¾´®Ðлò²¢ÐУ©¡£Á÷µÄ±äÌå°üÀ¨ÔʼµÄ int¡¢long ºÍ double
ÀàÐÍ£¬ÒÔ¼°ÀàÐÍ»¯µÄ¶ÔÏóÁ÷¡£
еÄÁ÷ API ¹ýÓÚ¸´ÔÓ£¬±¾ÎĺÜÄÑÍêÕûµØ½²ÊöËüÃÇ£¬Òò´ËÎÒ½«Öصã·ÅÔÚÁ˲¢·¢ÐÔ·½Ãæ¡£²Î¼û
²Î¿¼×ÊÁÏ ²¿·ÖÖйØÓÚÁ÷µÄ¸ü¼ÓÏêϸµÄ˵Ã÷¡£
Çåµ¥ 5 ÏÔʾÁ˱༾àÀë×î¼ÑÆ¥Åä´úÂëµÄÁíÒ»ÖÖ±äÌå¡£Õâ¸ö°æ±¾Ê¹ÓÃÁË Çåµ¥
1 ÖÐµÄ ChunkDistanceChecker À´½øÐоàÀë¼ÆË㣬²¢Ïñ Çåµ¥ 2 ʾÀýÖеÄÄÇÑùʹÓÃÁË
CompletableFuture£¬µ«Õâ´ÎÎÒʹÓÃÁËÁ÷À´»ñµÃ×î¼ÑµÄÆ¥Åä½á¹û¡£
Çåµ¥ 5. ʹÓÃÁ÷µÄ CompletableFuture
public class CompletableFutureStreamDistance extends TimingTestBase { private final List<ChunkDistanceChecker> chunkCheckers;
...
public DistancePair bestMatch(String target) {
return chunkCheckers.stream()
.map(checker -> CompletableFuture.supplyAsync(()
-> checker.bestDistance(target)))
.collect(Collectors.toList())
.stream()
.map(future -> future.join())
.reduce(DistancePair.worstMatch(), (a, b) ->
DistancePair.best(a, b));
}
} |
λÓÚÇåµ¥ 5 µ×²¿µÄ¶àÐÐÓï¾äʹÓÃÁ˼ò±ãµÄÁ÷ API À´Íê³ÉËùÓй¤×÷£º
chunkCheckers.stream() ´Ó List<ChunkDistanceChecker>
´´½¨Ò»¸öÁ÷¡£
1¡¢.map(checker -> ... ¶ÔÁ÷ÖеÄֵʹÓÃÓ³É䣬Õâ¸öÀý×ÓÖУ¬Ê¹ÓÃÁËÓë
Çåµ¥ 2 Àý×ÓÖÐÏàͬµÄ¼¼ÊõÀ´¹¹ÔìÒ»¸öÕë¶Ô ChunkDistanceChecker.bestDistance()
·½·¨µÄÒì²½Ö´Ðнá¹ûµÄ CompletableFuture¡£
2¡¢.collect(Collectors.toList()) ½«ÖµÊÕ¼¯µ½Ò»¸öÁбíÖУ¬È»ºóÓÃ
.stream() ½«Ëüת»»»ØÎªÁ÷¡£
3¡¢.map(future -> future.join()) µÈ´ýÿ¸ö
future µÄ½á¹û±äΪ¿ÉÓ㬶ø .reduce(... ͨ¹ý¶Ôǰ×î¼Ñ½á¹ûÓë×îнá¹û·´¸´Ó¦Óà DistancePair.best()
·½·¨À´ÕÒ³ö×î¼ÑÖµ¡£
ÎÞ¿É·ñÈÏ£¬ÕâÈÃÈ˸е½ÓÐЩ»ìÂÒ¡£ÔÚÄú²»Ïë¶ÁÏÂȥ֮ǰ£¬ÎÒÏòÄú±£Ö¤ÏÂÒ»°æÒ»¶¨»á¸ü¼òµ¥¡¢¸üÇåÎú¡£Çåµ¥
5 µÄÄ¿µÄÊÇÈÃÄúÁ˽âÈçºÎʹÓÃÁ÷À´´úÌæÆÕͨѻ·¡£
Çåµ¥ 5 µÄ´úÂë»á¸ü¼òµ¥£¬ÒòΪËüûÓнøÐжà´Îת»»£¨´ÓÁ÷µ½ÁбíÔٻص½Á÷£©¡£ÔÚÕâ¸öÀý×ÓÖÐÐèҪת»»£¬·ñÔòÔÚ´´½¨
future ºó£¬´úÂë¾Í»áÁ¢¿Ì¿ªÊ¼µÈ´ý CompletableFuture.join() ·½·¨¡£
²¢ÐÐÁ÷
ÐÒÔ˵ÄÊÇ£¬´æÔÚ×Å±È Çåµ¥ 5 ¸ü¼òµ¥µÄÔÚÁ÷ÉÏʵÏÖ²¢ÐвÙ×÷µÄ·½·¨¡£Ë³ÐòÁ÷¿ÉÒÔ±äΪ²¢ÐÐÁ÷£¬¶ø²¢ÐÐÁ÷¿É×Ô¶¯¿ç¶à¸öÏ̹߳²Ïí¹¤×÷£¬²¢ÔÚÉÔºóÊÕ¼¯½á¹û¡£Çåµ¥
6 ÏÔʾÁËÈçºÎʹÓÃÕâÖÖ·½·¨´Ó List<ChunkDistanceChecker> ÖÐÕÒµ½×î¼ÑÆ¥ÅäÏî¡£
Çåµ¥ 6. ʹÓÃÅúÁ¿²¢ÐÐÁ÷µÄ×î¼ÑÆ¥Åä
public class ChunkedParallelDistance extends TimingTestBase { private final List<ChunkDistanceChecker> chunkCheckers; ... public DistancePair bestMatch(String target) { return chunkCheckers.parallelStream() .map(checker -> checker.bestDistance(target)) .reduce(DistancePair.worstMatch(), (a, b) -> DistancePair.best(a, b)); } } |
ÔÙ´ÎÉêÃ÷£¬Î»ÓÚĩβµÄ¶àÐÐÓï¾äÍê³ÉÁËËùÓй¤×÷¡£ºÍÔÚ Çåµ¥ 5 ÖÐÒ»Ñù£¬Óï¾äÒ»¿ªÊ¼´ÓÁÐ±í´´½¨Á÷£¬µ«Õâ¸ö°æ±¾Ê¹ÓÃÁË
parallelStream() ·½·¨À´»ñÈ¡ÓÃÓÚ²¢Ðд¦ÀíµÄÁ÷¡££¨Äú»¹¿ÉÒÔ½«ÆÕͨÁ÷ת»»Îª²¢Ðд¦ÀíµÄÁ÷£¬Ö»ÐèÔÚÁ÷Éϵ÷ÓÃ
parallel() ·½·¨¼´¿É¡££©½ÓÏÂÀ´µÄ²¿·ÖÊÇ .map(checker -> checker.bestDistance(target))£¬ÓÃÓÚÔÚ´óÁ¿ÒÑÖªµ¥´ÊÖÐÕÒµ½×î¼ÑÆ¥Åä¡£×îºóÒ»²¿·ÖÊÇ
.reduce(...£¬ÓÃÓÚÔÚËùÓÐÊý¾Ý¿éÖÐÊÕ¼¯×î¼Ñ½á¹û£¬ÕâÒ»µãÒ²ºÍ Çåµ¥ 5 ÖÐÏàͬ¡£
²¢ÐÐÁ÷»á²¢ÐÐÖ´ÐÐijЩ²½Ö裬±ÈÈç map ºÍ filter ²Ù×÷¡£Òò´ËÔÚºǫ́£¬Çåµ¥
6 ´úÂëÔÚ¼õÊý²½ÖèÖÐÕûºÏ½á¹û֮ǰ£¬»á½«Ó³Éä²½Öè·ÖÉ¢µ½¶à¸öÏß³ÌÉÏ£¨²»Ò»¶¨Òª°´ÕÕÌØ¶¨µÄ˳Ðò£¬ÒòΪ½á¹ûµÄµ½À´ºÍ²úÉú½á¹ûµÄ²Ù×÷ÊDz¢Ðеģ©¡£
ÔÚÁ÷ÖУ¬¶ÔÒªÍê³ÉµÄ¹¤×÷½øÐзֽâµÄÄÜÁ¦È¡¾öÓÚÁ÷ÖÐʹÓÃµÄ java.util.Spliterator<T>
нӿڡ£´ÓÃû³Æ¿ÉÒÔ¿´³öÀ´£¬Spliterator ÀàËÆÓÚ Iterator¡£ºÍ Iterator Ò»Ñù£¬Ê¹ÓÃ
Spliterator ÿ´Î¿ÉÒÔ´¦Àíij¸öÔªËØ¼¯ºÏÖеÄÒ»¸öÔªËØ ¡ª ²»ÊÇ´Ó Spliterator ÖлñÈ¡ÔªËØ£¬¶øÊÇʹÓÃ
tryAdvance() »ò forEachRemaining() ·½·¨¶ÔÔªËØÓ¦ÓòÙ×÷¡£µ« Spliterator
»¹¿ÉÒÔÓÃÓÚ¹À¼ÆÆäÖб£´æµÄÔªËØÊýÁ¿£¬¶øÇÒ»¹¿ÉÒÔÏñϸ°û·ÖÁÑÒ»Ñù±äΪһ·ÖΪ¶þ¡£ÕâЩÐÂÔö¼ÓµÄÄÜÁ¦ÈÃÁ÷²¢Ðд¦Àí´úÂë¿ÉÒԺܷ½±ãµØ½«¹¤×÷·Ö²¼µ½¶à¸ö¿ÉÓÃÏß³ÌÉÏÍê³É¡£
Çåµ¥ 6 ÖеĴúÂë¿ÉÄÜÈÃÄú¾õµÃËÆÔøÏàʶ£¬ÕâÊÇÒòΪËüÓë´ËϵÁÐ ÊׯªÎÄÕ ÖеÄ
Scala ²¢Ðм¯ºÏÀý×ӷdz£ÏàËÆ£º
def bestMatch(target: String) = matchers.par.map(m => m.bestMatch(target)). foldLeft(DistancePair.worstMatch)((a, m) => DistancePair.best(a, m)) |
ÎÞÂÛÓï·¨»¹ÊDzÙ×÷¶¼´æÔÚһЩ²î±ð£¬µ«Êµ¼ÊÉÏ£¬Java 8 ²¢ÐÐÁ÷´úÂëºÍ Scala
²¢Ðм¯ºÏ´úÂëÊÇÔÚÒÔÏàͬµÄ·½Ê½×ö×ÅͬÑùµÄÊÂÇé¡£
È«³ÌʹÓÃÁ÷
Æù½ñΪֹ£¬ËùÓÐÀý×Ó¾ù±£ÁôÁË´ËϵÁÐ ÊׯªÎÄÕ ÖбȽÏÈÎÎñʹÓõķֿé½á¹¹£¬ÔÚÀϰ汾µÄ
Java ÖУ¬ÕâÖֽṹÊǸßЧ´¦Àí²¢ÐÐÈÎÎñËù±ØÐèµÄ¡£Java 8 ²¢ÐÐÁ÷Éè¼ÆÓÃÓÚ´¦ÀíËüÃÇ×Ô¼ºµÄµÄ¹¤×÷·Ö¹¤£¬Òò´ËÄúÄܹ»ÒÔÁ÷µÄÐÎʽ´«µÝÒ»¸öÒª´¦ÀíµÄÖµ¼¯£¬È»ºóÄÚÖõIJ¢·¢´¦Àí»úÖÆ»á½«Õâ¸ö¼¯ºÏ·Ö½âµ½¸÷¸ö¿ÉÓõĴ¦ÀíÆ÷½øÐд¦Àí¡£
Èç¹û³¢ÊÔ½«ÕâÖÖ·½·¨ÓÃÓڱ༾àÀëÈÎÎñ£¬Ôò»á³öÏֺܶàÎÊÌâ¡£Èç¹û½«´¦Àí²½ÖèÈ«²¿Á´½Óµ½Ò»¸ö¹ÜµÀ£¨Á÷²Ù×÷ÐòÁеĹٷ½½Ð·¨£©ÖУ¬ÄÇô¿ÉÒÔÖ»½«Ã¿¸ö²½ÖèµÄ½á¹û´«¸ø¹ÜµÀµÄÏÂÒ»½×¶Î¡£Èç¹ûÏë»ñµÃ¶à¸ö½á¹û£¨±ÈÈç×î¼Ñ¾àÀëÖµºÍ±à¼¾àÀëÈÎÎñÖÐʹÓõĶÔÓ¦ÒÑÖªµ¥´Ê£©£¬Ôò±ØÐëÒÔ¶ÔÏóµÄÐÎʽ´«µÝËüÃÇ¡£µ«ÊÇÓë·Ö¿é·½·¨Ïà±È£¬ÎªÃ¿´Î±È½ÏµÄ½á¹û´´½¨Ò»¸ö¶ÔÏ󽫻áËðº¦Ö±½ÓÁ÷·½·¨µÄÐÔÄÜ¡£ÉõÖÁ¸üÔãµÄÇé¿öÊÇ£¬±à¼¾àÀë¼ÆËã»áÖØÓÃÒ»¶ÔÒÑ·ÖÅäµÄÊý×é¡£Õâ¶ÔÊý×éÎÞ·¨ÔÚ²¢ÐмÆËãÖ®¼ä¹²Ïí£¬Òò´ËÐèҪΪÿ´Î¼ÆËãÖØÐ·ÖÅäÊý×é¡£
ÐÒÔ˵ÄÊÇ£¬Á÷ API Ö§³ÖÄúÓÐЧµØÓ¦¶ÔÕâÖÖÇé¿ö£¬µ«»¹ÐèÒªÁíÍâ×öһЩ¹¤×÷¡£Çåµ¥
7 ÑÝʾÁËÈçºÎʹÓÃÁ÷À´´¦ÀíÕû¸ö¼ÆËã¹ý³Ì£¬Í¬Ê±²»»á´´½¨Öмä¶ÔÏó»ò¶îÍâµÄ¹¤×÷Êý×é¡£
Çåµ¥ 7. ÿ´Î±à¼¾àÀë±È½ÏµÄÁ÷´¦Àí
public class NonchunkedParallelDistance extends TimingTestBase { private final String[] knownWords; ... private static int editDistance(String target, String known, int[] v0, int[] v1) { ... } public DistancePair bestMatch(String target) { int size = target.length() + 1; Supplier<WordChecker> supplier = () -> new WordChecker(size); ObjIntConsumer<WordChecker> accumulator = (t, value) -> t.checkWord(target, knownWords[value]); BiConsumer<WordChecker, WordChecker> combiner = (t, u) -> t.merge(u); return IntStream.range(0, knownWords.length).parallel() .collect(supplier, accumulator, combiner).result(); } private static class WordChecker { protected final int[] v0; protected final int[] v1; protected int bestDistance = Integer.MAX_VALUE; protected String bestKnown = null; public WordChecker(int length) { v0 = new int[length]; v1 = new int[length]; } protected void checkWord(String target, String known) { int distance = editDistance(target, known, v0, v1); if (bestDistance > distance) { bestDistance = distance; bestKnown = known; } else if (bestDistance == distance) { bestKnown = null; } } protected void merge(WordChecker other) { if (bestDistance > other.bestDistance) { bestDistance = other.bestDistance; bestKnown = other.bestKnown; } else if (bestDistance == other.bestDistance) { bestKnown = null; } } protected DistancePair result() { return (bestKnown == null) ? new DistancePair(bestDistance) : new DistancePair(bestDistance, bestKnown); } } } |
Çåµ¥ 7 ʹÓÃÒ»¸ö¿É±äµÄ½á¹ûÈÝÆ÷ÀࣨÕâÀïʹÓõÄÊÇ WordChecker
ÀࣩÀ´ÕûºÏ½á¹û¡£bestMatch() ·½·¨Ê¹ÓÃÈý¸ö lambdas ÐÎʽµÄ»î¶¯²¿·ÖʵÏÖÁ˱Ƚϡ£
Supplier<WordChecker> supplier
lambda Ìṩ½á¹ûÈÝÆ÷µÄʵÀý¡£
ObjIntConsumer<WordChecker> accumulator
lambda ½«Ò»¸öÐÂÖµÊÕ¼¯µ½½á¹ûÈÝÆ÷ÖС£
BiConsumer<WordChecker, WordChecker>
combiner lambda ½«Á½¸ö½á¹ûÈÝÆ÷ºÏ²¢£¬´Ó¶øÊµÏÖÖµµÄÕûºÏ¡£¶¨ÒåÁËÕâÈý¸ö lambdas Ö®ºó£¬×îºóÒ»Ìõ
bestMatch() Óï¾ä½«ÎªÒÑÖªµ¥´ÊÊý×éÖеÄË÷Òý´´½¨Ò»¸ö int ÖµµÄ²¢ÐÐÁ÷£¬²¢½«Á÷´«µÝ¸ø IntStream.collect()
·½·¨¡£collect() ·½·¨Ê¹ÓÃÈý¸ö lambdas À´Íê³Éʵ¼ÊµÄ¹¤×÷¡£
Java 8 ²¢·¢ÐÔÄÜ
ͼ 1 ÏÔʾÁËÔÚÎÒʹÓà Oracle's Java 8 for 64-bit
Linux? µÄËÄºË AMD ϵͳÉÏÔËÐвâÊÔ´úÂëʱ£¬¶Ô²»Í¬´óСµÄ¿é²âÁ¿ÐÔÄÜʱµÄÐÔÄܱ仯¡£Ó뱾ϵÁÐ ÊׯªÎÄÕÂ
ÖеĶ¨Ê±²âÊÔÒ»Ñù£¬½«Ã¿¸öÊäÈëµÄµ¥´ÊÒÀ´ÎÓë 12,564 ¸öÒÑÖªµ¥´Ê½øÐбȽϣ¬¶øÃ¿¸öÈÎÎñ¶¼»áÔÚÒÑÖªµ¥´ÊµÄ·¶Î§ÄÚÕÒµ½×î¼ÑÆ¥Åä¡£ËùÓÐ
933 ¸öƴд´íÎóµÄÊäÈëµ¥´Ê½«±»·´¸´ÔËÐУ¬µ«ÔÚÿ´Î´«µÝ¸ø JVM ½øÐд¦ÀíµÄ¼ä϶»á³öÏÖÔÝÍ£¡£Í¼ 1 ÖÐʹÓÃÁË
10 ´Î´«µÝºóµÄ×î¼Ñʱ¼ä¡£×îÖյĿé´óС 16,384 ´óÓÚÒÑÖªµ¥´ÊµÄÊýÁ¿£¬Òò´ËÕâ¸öÀý×ÓÏÔʾµÄÊǵ¥Ï̵߳ÄÐÔÄÜ¡£¶¨Ê±²âÊÔÖаüº¬µÄʵÏÖÊDZ¾ÎÄÖеÄËÄÖÖÖ÷Òª±äÌåºÍÊׯªÎÄÕÂÖеÄ×ÜÌå×î¼Ñ±äÌ壺
CompFuture£ºÇåµ¥ 2 ÖÐµÄ CompletableFutureDistance0
CompFutStr£ºÇåµ¥ 5 ÖÐµÄ CompletableFutureStreamDistance
ChunkPar£ºÇåµ¥ 6 ÖÐµÄ ChunkedParallelDistance
ForkJoin£ºÊׯªÎÄÕ ÖÐÇåµ¥ 3 ÖÐµÄ ForkJoinDistance
NchunkPar£ºÇåµ¥ 7 ÖÐµÄ NonchunkedParallelDistance

ͼ 1. Java 8 ÐÔÄÜ
ͼ 1 ÏÔʾÐ嵀 Java 8 ²¢ÐÐÁ÷·½·¨µÄÐÔÄܷdz£Í»³ö£¬ÌرðÊÇÍêÈ«Á÷»¯µÄ
Çåµ¥ 7 NchunkPar¡£¶¨Ê±²âÊÔ½á¹û±íÏÖ³öÓÃÓÚÏû³ý¶ÔÏó´´½¨µÄÓÅ»¯Ð§¹û£¨Ö»ÓÐͼ±íÖеÄÒ»¸öÖµ£¬ÒòΪÕâÖÖ·½·¨²»Ê¹Óÿé´óС£©£¬ÕâÓëÆäËûÈκη½·¨µÄ×î¼ÑЧ¹ûÏ൱¡£CompletableFuture
·½·¨ÔÚÐÔÄÜ·½Ãæ±íÏÖÉÔÈõ£¬µ«Õâ²¢²»ÒâÍ⣬ÒòΪÕâ¸öÀý×Ó²¢Î´ÕæÕýÌåÏÖ³ö¸ÃÀàµÄÇ¿´ó¹¦ÄÜ¡£Çåµ¥ 5 ChunkPar
ʱ¼ä´óÖÂÓë ÊׯªÎÄÕ ÖÐ ForkJoin ´úÂëÏ൱£¬µ«¶Ô¿é´óСµÄÃô¸ÐÐÔÓÐËù½µµÍ¡£¶ÔÓÚÒ»´ÎÐÔ²âÊÔ´óÁ¿µ¥´ÊµÄËùÓбäÌ壬Äú»á¿´µ½¿é´óС½ÏСʱÐÔÄܸü²î£¬ÒòΪ´´½¨¶ÔÏóµÄ¿ªÏú½Ï֮ʵ¼ÊµÄ¼ÆË㹤×÷¸ü¸ß¡£
ºÍ ÊׯªÎÄÕ ÖеĶ¨Ê±²âÊÔ½á¹ûÏàͬ£¬ÕâЩ½á¹ûÖ»ÄÜÓÃ×÷ÐÔÄܲο¼£¬¾ßÌåÐÔÄÜÓ¦µ±ÒÔÄú×Ô¼ºµÄÓ¦ÓóÌÐòΪ׼¡£ÕâÀï×îÖØÒªµÄÒ»Ìõ¾ÑéÊÇ£¬Ö»ÓÐÕýȷʹÓÃеÄ
Java 8 ²¢ÐÐÁ÷£¬Ëü²ÅÄܱíÏÖ³öÓÅÒìµÄÐÔÄÜ¡£½«ÓÅÒìÐÔÄÜÓëÁ÷µÄ¹¦ÄÜÐÔ±àÂ뷽ʽµÄ¿ª·¢Óŵã½áºÏÆðÀ´£¬¾ÍÄÜÔÚÖµ¼¯ÉϽøÐмÆËãʱ»ñµÃ³É¹¦¡£
½áÊøÓï
Java 8 Ϊ¿ª·¢ÈËÔ±Ìá¹©Ò»Ð©ÖØÒªµÄй¦ÄÜ¡£²¢ÐÐÁ÷ʵÏÖ×ßÔÚ²¢·¢ÐÔÁìÓòÇ°ÑØ£¬Ëٶȸü¿ìÇÒÒ×ÓÚʹÓã¬ÌرðÊÇÔÚÓëÓÃÓÚ¹¦ÄÜÐÔ±à³Ì·ç¸ñµÄ
lambda ±í´ïʽ£¨ËüÄܹ»ÇåÎú¶ø×¼È·µØ±í´ïÓû§Òâͼ£©½áºÏʹÓÃʱ¡£µ±´¦Àí¶ÀÁ¢²Ù×÷ʱ£¬Ð嵀 CompletableFuture
À໹¿ÉÒÔ½µµÍ²¢·¢ÐÔ±à³ÌµÄÄѶȣ¬ÔÚÕâÖÖÇé¿öϲ»ÒËʹÓÃÁ÷Ä£ÐÍ¡£
ÏÂһƪ JVM ²¢·¢ÐÔ ÎÄÕ½«»áת¶ø½éÉÜ Scala£¬²¢Ì½ÌÖ´¦ÀíÒì²½¼ÆËãµÄÁíÒ»ÖÖÓÐȤ·½Ê½¡£½èÖú
async ºê£¬Äú¿ÉÒÔд³öÓë½øÐÐ˳Ðò·Ö¿é²Ù×÷ÏàËÆµÄ´úÂ룬²¢Í¨¹ý Scala ½«´úÂëת»»ÎªÍêÈ«·Ç·Ö¿éµÄ½á¹¹¡£ÎÒ½«¸ø³öһЩÀý×ÓÀ´ËµÃ÷ÕâÖÖ¹¦ÄܵÄÓô¦ºÍʵÏÖ¡£ËÖªµÀÄØ
¡ª Ò²ÐíÕâЩÀ´×Ô Scala µÄй¦Äܽ«»á°üº¬ÔÚ Java 9 ÖС£ |