2012-08-10 16 views
6

मैं यह समझने की कोशिश कर रहा हूं कि Callable एक अलग थ्रेड पर चलने पर मान वापस करने में सक्षम है।हुड के नीचे एक कॉल करने योग्य काम कैसे करता है? कॉल करने योग्य ऑब्जेक्ट के लिए मूल्य वापस करने के लिए यह कैसे संभव है?

मैं वर्गों Executors, AbstractExecutorService, ThreadPoolExecutor और FutureTask में देख रहा हूँ, सभी उपलब्ध java.util.concurrent पैकेज में।

आप निष्पादकों में एक विधि को कॉल करके एक निष्पादक सेवा सेवा बनाते हैं (उदा। newSingleThreadExecutor())। फिर आप ExecutorService.submit(Callable c) के साथ एक कॉल करने योग्य ऑब्जेक्ट पास कर सकते हैं।

call() विधि ExecutorService द्वारा प्रदान किए गए थ्रेड द्वारा चलाया जाता है, जहां लौटाई गई वस्तु कॉलिंग थ्रेड पर वापस "कूद" करती है? इस सरल उदाहरण में

देखो:

1 ExecutorService executor = Executors.newSingleThreadExecutor(); 
2 public static void main(String[] args) { 
3  Integer i = executor.submit(new Callable<Integer>(){ 
4   public Integer call() throws Exception { 
5    return 10; 
6   } 
7  }).get(); 
8  System.out.print("Returns: " + i + " Thread: " + Thread.currentThread.getName()); 
9  // prints "10 main" 
10 } 

कैसे है यह संभव है कि कॉल विधि है, जो एक अलग थ्रेड द्वारा चलाया जाता है, में पूर्णांक पूर्णांक वस्तु में लौट आता है (पंक्ति 3) तो यह कर सकते हैं मुख्य धागे (पंक्ति 7) में System.out कथन द्वारा मुद्रित किया जाए?

क्या ExecutorService से पहले अपने धागे को चलाने के लिए मुख्य थ्रेड चलाने के लिए संभव नहीं है, ताकि System.out statement प्रिंट नल हो?

+0

इस कोड में कुछ संकलन त्रुटियां हैं; उदाहरण के लिए, 'execor.submit' एक भविष्य देता है, एक इंटीजर नहीं, और 'currentThread' एक विधि है जिसे कॉल करने की आवश्यकता होती है। अगर कोई कामकाजी उदाहरण देखने की परवाह करता है, तो http://ideone.com/myoMB –

+0

देखें, मैं उस कोड को हाथ से लिख रहा था। :-) मैं आपके उदाहरण पर एक नज़र डालेगा। – Rox

+0

अरे कोई समस्या नहीं, मैं बस सहायक होने की कोशिश कर रहा था। यह एक अच्छा प्रश्न है। +1 –

उत्तर

8

कैसे है यह संभव है कि कॉल विधि है, जो एक अलग थ्रेड द्वारा चलाया जाता है, में पूर्णांक पूर्णांक वस्तु में लौट आता है

ExecutorService.submit(...) करता नहीं वापसी call() से वस्तु यह लेकिन Future<Integer> लौटाता है और आप उस ऑब्जेक्ट को पाने के लिए Future.get() विधि का उपयोग कर सकते हैं। नीचे उदाहरण कोड देखें।

क्या एक्जीक्यूटर्स सर्विस ने अपना धागा चलाने से पहले मुख्य धागे को चलाने के लिए संभव नहीं है, ताकि System.out कथन प्रिंट नल हो?

नहीं, भविष्य में get() विधि नौकरी खत्म होने तक प्रतीक्षा करती है। यदि call() शून्य वापस लौटा तो get() अन्यथा यह वापस लौटाएगा (और प्रिंट) 10 गारंटीकृत।

<T> Future<T> submit(Callable<T> task): निष्पादन के लिए एक मूल्य लौटने कार्य सबमिट करता है और एक भविष्य कार्य के लंबित परिणाम का प्रतिनिधित्व करने देता है

Future<Integer> future = executor.submit(new Callable<Integer>(){ 
    public Integer call() throws Exception { 
     return 10; 
    } 
}); 
try { 
    // get() waits for the job to finish before returning the value 
    // it also might throw an exception if your call() threw 
    Integer i = future.get(); 
    ... 
} catch (ExecutionException e) { 
    // this cause exception is the one thrown by the call() method 
    Exception cause = e.getCause(); 
    ... 
} 
+0

आपके उत्तर के लिए धन्यवाद! प्रतीक्षा कहां होती है? यह कुछ सिंक्रनाइज़ेशन होना चाहिए ताकि कॉलिंग थ्रेड (उदा। मुख्य धागा) निष्पादक सेवा के लिए अपना कार्य पूरा करने के लिए प्रतीक्षा कर सके। मैंने फ्यूचरटास्क और थ्रेडपूल एक्स्सेलर में देखा है और इस तरह के सिंक्रनाइज़ेशन को देख सकते हैं। – Rox

+0

क्या यह इस तरह काम करता है, कि मुख्य थ्रेड 'Future.get()' विधि में निष्पादित करता है, निष्पादक सेवा 'RunnableFuture.run()' विधि में प्रवेश करने से पहले, लेकिन मुख्य विधि को निष्पादक सेवा को चलाने के लिए इंतजार करना पड़ता है () विधि और जब यह है, यह मुख्य थ्रेड को get() विधि के साथ जाने के लिए नोटिस करता है? – Rox

+2

'भविष्य.get() 'प्रतीक्षा करता है। 'फ्यूचरटास्क' के अंदर मेरा मानना ​​है कि 'अधिग्रहण किया गया है (0)' और फिर 'doAququireSharedInterruptibly (...)' सिंक्रनाइज़ेशन और प्रतीक्षा करता है। सिंक्रनाइज़ेशन 'अस्थिर 'के साथ किया जाता है। – Gray

4

ExecutorService.submit() विधि पर एक नज़र डालें। भविष्य की विधि प्राप्त करने से कार्य पूरा होने पर कार्य पूरा हो जाएगा। आप तुरंत एक कार्य के लिए इंतजार को अवरोधित करना चाहते हैं, तो आप फार्म के निर्माण का उपयोग कर सकते result = exec.submit(aCallable).get();


प्र Isn't यह संभव से पहले ExecutorService है के लिए मुख्य थ्रेड चलाने के लिए अपना धागा चलाएं, ताकि System.out कथन प्रिंट नल हो?

->Future<T>.get() गणना पूर्ण करने के लिए आवश्यक होने पर प्रतीक्षा करता है, और फिर इसके परिणाम को पुनर्प्राप्त करता है।

+0

उत्तर देने के लिए धन्यवाद। ग्रे के जवाब पर मेरा प्रश्न देखें। सिंक्रनाइज़ेशन कहां होता है ताकि मुख्य धागा निष्पादक सेवा के लिए अपना कार्य पूरा करने का इंतजार कर सके? – Rox

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