2013-08-02 23 views
26

Ben bir java kütüphanesi etrafında küçük bir scala sarıcı yazma sürecindeim.ListenableFuture tocala Gelecek

  • yürütmek (sorgu):

bu bağlamda ListenableFuture olan ListenableFuture [Sonuç]:

  • asyncExecute (sorgu) Sonuç

    java kütüphanesi 2 yöntem açığa bir amacı QueryExecutor sahip guava kütüphanesinden biri.

    Benim scala sarmalayıcımın java nesnesi yerine bir Gelecek [Sonuç] döndürmesini istiyorum, ancak bunu gerçekleştirmenin en iyi yolunun ne olduğundan emin değilim.

    future { 
        executor.execute(query) 
    } 
    

    ve

    val p = promise[Result] 
    val guavaFuture = executor.asyncExecute(query) 
    
    Futures.addCallback(guavaFuture, new FutureCallback[Result] { 
        def onFailure(t: Throwable) { 
        p.failure(t) 
        } 
    
        def onSuccess(result: Result) { 
        p.success(result) 
        } 
    }) 
    
    p.future 
    

    merak yöntem en iyisi am: İşte ile geldi 2 çözümleridir. Benim sezgim, birincisi, bir Gelecek'i geri verirken, yürütme çağrısı bir cevap beklerken, ikincisi gerçekten engellenmemesi gerektiği gibi görünüyorsa da, bir iş parçacığını hala engelleyecektir. Her yöntemin artıları/eksileri hakkında herhangi bir yorum var mı?

  • +2

    size 4 işlemci bildiğinizi varsayalım. Bu durumda varsayılan 'ExecutionContext' 4 işçiden oluşur. Her bir 'gelecek {executor.execute (query)}' 1 çalışanı engeller, bu nedenle 4 "futures" programınızı tamamen engeller. İşlemleri engellemek için ek 'ExecutionContext' yaratabilirsiniz, ancak bazı ek yükler olacaktır. – senia

    +0

    Teşekkürler @senia, düşündüğüm buydu. İlk kod, arayanın bakış açısından async'tır, ancak yine de ExecutionContext'in bir parçasını engelleyecektir, ikincisi ise gerçekten bloke etmemektedir (asyncExecute'un non-bloke edici IO kullandığını varsayarak). Bunun çok basit bir soru olduğunu düşünüyorum ama Promises'e pek aşina değilim. – vptheron

    +1

    Bunu benzer (ya da hatta özdeş) bir gereksinim için yararlı buldum: https://github.com/eigengo/activator-akka-cassandra/blob/master/src/main/scala/core/cassandra.scala – Gavin

    cevap

    37

    İkinci seçenek en iyisi, herşeyi eşzamansız tutar. ama ... sen yeniden kullanılabilir kalıbı içine bir iyi ve soyut bir çözüm yapabilirsiniz:

    implicit class RichListenableFuture[T](lf: ListenableFuture[T]) { 
        def asScala: Future[T] = { 
        val p = Promise[T]() 
        Futures.addCallback(lf, new FutureCallback[T] { 
         def onFailure(t: Throwable): Unit = p failure t 
         def onSuccess(result: T): Unit = p success result 
        }) 
        p.future 
        }  
    } 
    

    Daha sonra sadece çağırabilirsiniz:

    executor.asyncExecute(query).asScala 
    
    +1

    Harika bir çözüm. ListenableFuture arabirim kodumun ne kadar daha temiz olduğuna inanamıyorum bu örtük –

    +2

    Çok hoş. Promise [T] ' – raam86

    +0

    kullanarak daha soyut olabilir Daha fazla yardım edemezsiniz ama toPromise aslında bir Gelecek döndürür. ;) Aksi takdirde, onu seviyorum! –

    İlgili konular