2016-06-20 41 views
5

CompletableFuture döndüren bir yöntem var. Geri dönmeden önce, bu yöntem CompletableFuture tamamlandıktan sonra çalıştırılan thenAccept ile bir blok ekler.Bir CompletableFuture öğesinin birden fazla thenAccept bloğunun yürütüldüğü düzen nedir?

Bu yöntemin arayıcısı, thenAccept numaralı başka bir bloğu da ekler. Açıkçası bu birden çok zincirli çağrı ile devam edebilir.

thenAccept tarafından verilen emirleri hangi sırayla çalıştırırsınız? Eklendikleri sıraya göre garanti ediliyor mu? Aksi takdirde, eklendikleri sırayla yürütüldükleri nasıl garanti edilebilir?

Not: Bu CompletableFuture ile kendi deneyime dayalı soruyorum ve bu article

+2

"thenAccept", ilk "bu" CompletableFuture öğesinin tamamlandığını ve yalnızca parametre işlevinin yürütüldüğünü belirtir. –

cevap

6

Bunları zincirleme olarak tamamlama aşamalarının bağımlılıkları modelliyoruz. Başka bir eylem C iki eylem A ve B zincirle varsa, olabildiğince, ilişkiler A → C ve B → C, ama A ve B ve bu nedenle aralarında hiçbir ilişki, bir başka deyişle, aralarında hiçbir sipariş ilişki dahil hiçbir ilişkisi yoktur tanımlamak 'bile yani

CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> { 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2)); 
    return "source"; 
}); 
base.thenAccept(s -> { 
    System.out.println("entered first consumer in "+Thread.currentThread()); 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
    System.out.println("leaving first consumer"); 
}); 
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2)); 
base.thenAccept(s -> { 
    System.out.println("entered second consumer in "+Thread.currentThread()); 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
    System.out.println("leaving second consumer"); 
}); 

entered first consumer in Thread[ForkJoinPool.commonPool-worker-1,5,main] 
entered second consumer in Thread[main,5,main] 
leaving second consumer 
leaving first consumer 

olsa gibi çok büyük olasılıkla baskı şey, tabii ki, bu konuda hiçbir garantisi yoktur olacaktır, yani peş peşe çalışacağını varsayıyoruz.


İki tüketici arasındaki bağımlılığınızı zorlamak için, bunları uygun şekilde zincirlemek zorundasınız, örn. Burada

CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> { 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2)); 
    return "source"; 
}); 
CompletableFuture<Void> next = base.thenAccept(s -> { 
    System.out.println("entered first consumer in "+Thread.currentThread()); 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
    System.out.println("leaving first consumer"); 
}); 
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2)); 
base.thenAcceptBoth(next, (s,ignored) -> { 
    System.out.println("entered second consumer in "+Thread.currentThread()); 
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
    System.out.println("leaving second consumer"); 
}).join(); 

, ikinci tüketici base sonucunu alacak base ve next, zincirlenmiş ancak geçiş belki hiç bir sonuç varsa normalde gerektirmez olan ( next 'nin tamamlanmasından bağlıdır Böyle bir senaryonuz varsa, tasarımınızı yeniden düşünmek istersiniz).

Alternatif olarak, değeri geçen bir Function ilk Consumer dönüştürmek, bu nedenle bunun için başka thenAccept aşama zincir izin vermek için, thenApply yoluyla zincir olabilir.