2010-01-29 14 views
19

मेरे पास कुछ कोड है जो किसी अन्य थ्रेड के लिए अनुरोध सबमिट करता है जो उस अनुरोध को अभी तक एक और थ्रेड सबमिट नहीं कर सकता है या नहीं। इससे Future<Future<T>> का रिटर्न प्रकार मिलता है। क्या यह Future<T> में तुरंत चालू करने के लिए कुछ गैर-जघन्य तरीका है जो पूरी भविष्य श्रृंखला के पूरा होने की प्रतीक्षा करता है?भविष्य <Future<T>> भविष्य में <T> में बदलने का कोई आसान तरीका है?

मैं पहले से ही अन्य मज़ेदार समवर्ती सामानों को संभालने और Google संग्रह के प्रतिस्थापन के रूप में और इसके कामकाजी के रूप में अच्छी तरह से काम करने के लिए गुवा पुस्तकालय का उपयोग कर रहा हूं लेकिन मुझे इस मामले के लिए कुछ नहीं मिल रहा है।)

public class UnwrapFuture<T> implements Future<T> { 
    Future<Future<T>> wrappedFuture; 

    public UnwrapFuture(Future<Future<T>> wrappedFuture) { 
     this.wrappedFuture = wrappedFuture; 
    } 

    public boolean cancel(boolean mayInterruptIfRunning) { 
     try { 
      return wrappedFuture.get().cancel(mayInterruptIfRunning); 
     } catch (InterruptedException e) { 
      //todo: do something 
     } catch (ExecutionException e) { 
      //todo: do something 
     } 
    } 
    ... 
} 

आप अपवादों कि मिल (से निपटने के लिए होगा बढ़ा सकते हैं लेकिन अन्य तरीकों नहीं कर सकते हैं:

+4

यदि आप कर सकते हैं तो यह सहायक होगा थोड़ा और संदर्भ जोड़ें। स्पष्ट जवाब है() को कॉल करना, लेकिन शायद यह नहीं है कि आप क्या चाहते हैं। –

+0

हो गया। क्षमा करें यह स्पष्ट नहीं था। – Nik

+0

लगता है जैसे आपको मोनाड – user

उत्तर

5

गुवा 13.0 Futures.dereference इसे करने के लिए जोड़ता है। इसे सादे Future<Future> के बजाय ListenableFuture<ListenableFuture> की आवश्यकता है। (एक सादे Future पर संचालन करने के लिए एक मेकलिस्टेबल कॉल की आवश्यकता होगी, जिनमें से प्रत्येक को कार्य के जीवनकाल के लिए एक समर्पित धागा की आवश्यकता होती है (जैसा कि विधि के नए नाम, JdkFutureAdapters.listenInPoolThread द्वारा स्पष्ट किया गया है)।

0

आप एक वर्ग की तरह बना सकते हैं।

+1

की आवश्यकता है जो मैं बचने की कोशिश कर रहा था। साथ ही आपके द्वारा प्राप्त की गई विधि को रद्द करने से श्रृंखला में पहला भविष्य पूरा होने तक प्रतीक्षा रद्द कर दिया जाएगा। निश्चित रूप से वह नहीं है जो मैं ढूंढ रहा हूं। – Nik

+2

"इसे भविष्य में में बदलें जो पूरी भविष्य श्रृंखला को पूरा करने की प्रतीक्षा कर रहा है?" ... मुझे नहीं लगता कि आप दूसरे भविष्य को रद्द कर सकते हैं जब तक कि आप इसे पकड़ न लें। लेकिन जब तक कि पहला भविष्य इसे वापस नहीं कर लेता तब तक आप इसे प्राप्त नहीं कर सकते। – Dave

+0

अच्छा पकड़ो। जबकि दूसरा भविष्य पहले द्वारा बनाया गया है, मुझे यकीन है कि आप अपने आप को ऐसे राज्य में ले जा सकते हैं जहां आपने पहला भविष्य रद्द कर दिया है लेकिन यह वैसे भी दूसरा बनाता है और आप इसे रद्द नहीं कर सकते हैं। मुझे यकीन है कि आप इसे पहले भविष्य में 'Futures.makeListenable' द्वारा ठीक कर सकते हैं और एक श्रोता जोड़ सकते हैं जो बदले में जंजीर भविष्य को तुरंत रद्द कर देता है। तब समस्या उस मामले के लिए परीक्षण हो जाती है। – Nik

0

यह मेरा पहला पड़ाव था लेकिन मुझे यकीन है कि इसमें बहुत गड़बड़ है। Futures.compress(f) जैसे कुछ के साथ इसे बदलने के लिए मुझे खुशी होगी।

public class CompressedFuture<T> implements Future<T> { 
    private final Future<Future<T>> delegate; 

    public CompressedFuture(Future<Future<T>> delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public boolean cancel(boolean mayInterruptIfRunning) { 
     if (delegate.isDone()) { 
      return delegate.cancel(mayInterruptIfRunning); 
     } 
     try { 
      return delegate.get().cancel(mayInterruptIfRunning); 
     } catch (InterruptedException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } catch (ExecutionException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } 
    } 

    @Override 
    public T get() throws InterruptedException, ExecutionException { 
     return delegate.get().get(); 
    } 

    @Override 
    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 
     long endTime = System.currentTimeMillis() + unit.toMillis(timeout); 
     Future<T> next = delegate.get(timeout, unit); 
     return next.get(endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 
    } 

    @Override 
    public boolean isCancelled() { 
     if (!delegate.isDone()) { 
      return delegate.isCancelled(); 
     } 
     try { 
      return delegate.get().isCancelled(); 
     } catch (InterruptedException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } catch (ExecutionException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } 
    } 

    @Override 
    public boolean isDone() { 
     if (!delegate.isDone()) { 
      return false; 
     } 
     try { 
      return delegate.get().isDone(); 
     } catch (InterruptedException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } catch (ExecutionException e) { 
      throw new RuntimeException("Error fetching a finished future", e); 
     } 
    } 
} 
1

मुझे लगता है कि भविष्य के अनुबंध को लागू करने के लिए यह सबसे अच्छा किया जा सकता है। मैंने जितना संभव हो उतना चालाक होने का प्रयास किया ताकि यह सुनिश्चित किया जा सके कि यह अनुबंध को पूरा करता है। विशेष रूप से टाइमआउट के साथ प्राप्त करने के कार्यान्वयन नहीं।

import java.util.concurrent.*; 

public class Futures { 
    public <T> Future<T> flatten(Future<Future<T>> future) { 
    return new FlattenedFuture<T>(future); 
    } 

    private static class FlattenedFuture<T> implements Future<T> { 
    private final Future<Future<T>> future; 

    public FlattenedFuture(Future<Future<T>> future) { 
     this.future = future; 
    } 

    public boolean cancel(boolean mayInterruptIfRunning) { 
     if (!future.isDone()) { 
     return future.cancel(mayInterruptIfRunning); 
     } else { 
     while (true) { 
      try { 
      return future.get().cancel(mayInterruptIfRunning); 
      } catch (CancellationException ce) { 
      return true; 
      } catch (ExecutionException ee) { 
      return false; 
      } catch (InterruptedException ie) { 
      // pass 
      } 
     } 
     } 
    } 

    public T get() throws InterruptedException, 
          CancellationException, 
          ExecutionException 
    { 
     return future.get().get(); 
    } 

    public T get(long timeout, TimeUnit unit) throws InterruptedException, 
                CancellationException, 
                ExecutionException, 
                TimeoutException 
    { 
     if (future.isDone()) { 
     return future.get().get(timeout, unit); 
     } else { 
     return future.get(timeout, unit).get(0, TimeUnit.SECONDS); 
     } 
    } 

    public boolean isCancelled() { 
     while (true) { 
     try { 
      return future.isCancelled() || future.get().isCancelled(); 
     } catch (CancellationException ce) { 
      return true; 
     } catch (ExecutionException ee) { 
      return false; 
     } catch (InterruptedException ie) { 
      // pass 
     } 
     } 
    } 

    public boolean isDone() { 
     return future.isDone() && innerIsDone(); 
    } 

    private boolean innerIsDone() { 
     while (true) { 
     try { 
      return future.get().isDone(); 
     } catch (CancellationException ce) { 
      return true; 
     } catch (ExecutionException ee) { 
      return true; 
     } catch (InterruptedException ie) { 
      // pass 
     } 
     } 
    } 
    } 
} 
7

अमरूद पुस्तकालयों का उपयोग करने वाला एक और संभावित कार्यान्वयन और बहुत आसान है।

import java.util.concurrent.*; 
import com.google.common.util.concurrent.*; 
import com.google.common.base.*; 

public class FFutures { 
    public <T> Future<T> flatten(Future<Future<T>> future) { 
    return Futures.chain(Futures.makeListenable(future), new Function<Future<T>, ListenableFuture<T>>() { 
     public ListenableFuture<T> apply(Future<T> f) { 
     return Futures.makeListenable(f); 
     } 
    }); 
    } 
} 
+0

ऐसा लगता है कि यह ऐसा करेगा और मुझे सभी भविष्य के हाथों को अमरूद में सौंपने दें। – Nik

संबंधित मुद्दे