2013-04-04 13 views
9

के साथ एक सिंक्रोनस विधि के साथ असीमित कॉल की एक श्रृंखला को लपेटना मेरा वर्तमान कोड परिणाम में समाप्त होने वाली असीमित प्रक्रियाओं की श्रृंखला का उपयोग करता है। मुझे इनमें से प्रत्येक को इस तरह से लपेटने की ज़रूरत है कि प्रत्येक को एक सिंक्रोनस विधि द्वारा रिटर्न वैल्यू के रूप में उपयोग किया जाता है। मैं ऐसा करने के लिए निष्पादक सेवाओं का उपयोग करना चाहता हूं, ताकि इनमें से कई एक ही समय में हो सकें। मुझे लगता है कि भविष्य मेरे कार्यान्वयन के लिए प्रासंगिक हो सकता है, लेकिन मैं ऐसा करने के लिए एक अच्छा तरीका नहीं समझ सकता।वापसी मूल्य

मैं अब क्या है:

public class DoAJob { 
    ResultObject result; 

    public void stepOne() { 
    // Passes self in for a callback 
    otherComponent.doStepOne(this); 
    } 

    // Called back by otherComponent once it has completed doStepOne 
    public void stepTwo(IntermediateData d) { 
    otherComponent.doStepTwo(this, d); 
    } 

    // Called back by otherComponent once it has completed doStepTwo 
    public void stepThree(ResultObject resultFromOtherComponent) { 
    result = resultFromOtherComponent; 
    //Done with process 
    } 
} 

यह आंतरिक रूप से बहुत अच्छी तरह से काम किया है, लेकिन अब मैं की तरह एक वापसी मान वाला एक तुल्यकालिक विधि में मेरी प्रक्रिया मैप करने की आवश्यकता:

public ResultObject getResult(){ 
    // ??? What goes here ??? 
} 

किसी को भी करता है इस सुन्दर तरीके से कार्यान्वित करने के बारे में एक अच्छा विचार है?

+1

इस बात में एक चीज गायब है: आप अंत में विभिन्न कार्यों के परिणाम ऑब्जेक्ट को अंत में कैसे जोड़ सकते हैं? –

+0

मुझे यकीन नहीं है कि मैं सवाल समझता हूं। आम तौर पर प्रक्रिया को नए DoAJob.stepOne() द्वारा लात मार दिया जाता है; stepTwo() विधि अन्य कॉम्पोनेंट से कॉलबैक द्वारा शुरू की जाती है। कॉलबैक की श्रृंखला के अंत में, परिणाम ऑब्जेक्ट सही ढंग से आबादी वाला है। किसी भी मध्यवर्ती डेटा बिट्स को अंतिम परिणाम में एकीकृत किया जाता है। – irondwill

उत्तर

0

मैं invokeAll(..) उपयोग करना चाहिये। यह निष्पादक को कार्यों का एक सेट सबमिट करेगा, और आखिरी बार पूरा होने तक ब्लॉक (सफलतापूर्वक/अपवाद के साथ)। इसके बाद यह पूर्ण भविष्य की वस्तुओं की एक सूची लौटाता है, ताकि आप उन पर लूप कर सकें और परिणामों को एकल परिणाम ऑब्जेक्ट में विलय कर सकें।

में आप एक तुल्यकालिक ढंग से केवल एक ही काम चलाना चाहते हैं, तो आपको निम्न का उपयोग कर सकते हैं:

executor.invokeAll(Collections.singleton(task)); 

--edit--

अब मुझे लगता है कि मैं बेहतर अपनी आवश्यकताओं को समझते हैं। मुझे लगता है कि आपको कार्यों के स्वतंत्र अनुक्रम सबमिट करने का एक तरीका चाहिए। कृपया this answer में पोस्ट किए गए कोड को देखें।

+0

मैंने अपने उदाहरण में इस कुएं को स्पष्ट नहीं किया, लेकिन पिछले चरण को पूरा करने पर कदम निर्भर हैं। उदाहरण के लिए, stepOne() को चरणऑन() के दूरस्थ समापन पर निष्पादित किया जाता है। stepTwo() अनिवार्य रूप से StepOne() – irondwill

7

यदि आप एक सिंक्रोनस/अवरुद्ध करने में एक एसिंक्रोनस ऑपरेशन (जो कॉलबैक निष्पादित करता है) को चालू करना चाहते हैं, तो आप अवरुद्ध कतार का उपयोग कर सकते हैं। यदि आप चाहें तो आप इसे भविष्य वस्तु में लपेट सकते हैं।

  1. एक अवरुद्ध कतार जो सिर्फ एक तत्व पकड़ कर सकते हैं परिभाषित करें:

    BlockingQueue<Result> blockingQueue = new ArrayBlockingQueue<Result>(1);

  2. अपने अतुल्यकालिक प्रक्रिया प्रारंभ करें (पृष्ठभूमि में चला जाएगा), और कॉलबैक ऐसी है कि इसके पूर्ण होने पर लिखते हैं, यह इसके परिणाम को ब्लॉकिंग कतार में जोड़ता है।

    Result result = blockingQueue.take();

मैं ऐसी ही कुछ लिखा से पहले (अग्रभूमि धागा जरूरतों:

  • अपने अग्रभूमि/आवेदन धागा में, यह पंक्ति है, जो ब्लॉक जब तक एक तत्व उपलब्ध हो जाता है से ले() है रिमोट मशीन से एसिंक्रोनस प्रतिक्रिया के लिए अवरुद्ध करने के लिए) भविष्य की तरह कुछ उपयोग करके, आप उदाहरण कोड here पा सकते हैं।

  • +0

    में नामित घटक के लिए पूर्णता कॉलबैक है इस उद्देश्य के लिए 0 सिंब्रोनस क्यूयू 'शायद इस उद्देश्य के लिए बेहतर है – ZhongYu

    +2

    मैं डरने से पहले वहां गया हूं (कोड जो मैं वास्तव में जुड़ा हुआ हूं)। एक सिंक्रोनसक्यूयू पृष्ठभूमि थ्रेड को अवरुद्ध करने या अपवाद प्राप्त करने का कारण बन सकता है, यदि कोई रेस स्थिति होती है जैसे बैकग्राउंड थ्रेड फोरग्राउंड थ्रेड से पहले() को पूरा करता है। यदि यह ओपी के रूप में भविष्य में लपेटा गया था, तो यह एक आम घटना हो सकती है यदि एप्लिकेशन ने Future.get() को कॉल करने से पहले कुछ और काम किया हो। – npgall

    0

    आप अपने हाथों गंदा प्राप्त करना चाहते, तो आप इस

    ResultObject result; 
    
    public void stepOne() 
    
        otherComponent.doStepOne(this); 
    
        synchronized(this) 
         while(result==null) this.wait(); 
        return result; 
    
    public void stepThree(ResultObject resultFromOtherComponent) 
    
        result = resultFromOtherComponent; 
    
        synchronized(this) 
         this.notify(); 
    

    कर सकते हैं या आप उच्च स्तर संगामिति उपकरण, BlockingQueue, सेमाफोर, CountdownLatch, Phaser, वगैरह वगैरह

    नोट की तरह उपयोग कर सकते हैं कि DoAJob धागा सुरक्षित नहीं है - एक ही समय में दो धागे stepOne पर कॉल करते समय परेशानी सुनिश्चित की गई।

    +0

    हाँ मैं ऐसा कुछ करने के लिए समाप्त हो सकता है क्योंकि यह एक काफी विशिष्ट उपयोग केस और वास्तुकला प्रतीत होता है। मैं उम्मीद कर रहा था कि प्रतीक्षा() लूप को लागू करने या बहुत से सिंक्रनाइज़() कॉल के साथ मेरे कोड को जंकिंग करने से बचें। – irondwill

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