java - जावा में रननेबल और कॉल करने योग्य इंटरफेस के बीच का अंतर




multithreading interface (7)

Runnable और Callable करने योग्य अनुप्रयोगों में अंतर क्या हैं। Callable में मौजूद रिटर्न पैरामीटर के साथ केवल अंतर है?

असल में, हाँ। इस सवाल के जवाब देखें। और कॉल करने योग्य के लिए Callable

यदि Callable करने योग्य सभी ऐसा करने योग्य हो तो दोनों को रखने की आवश्यकता क्या है?

क्योंकि Runnable इंटरफ़ेस Runnable करने योग्य सब कुछ नहीं कर सकता है!

Runnable जावा 1.0 के आसपास रहा है, लेकिन Callable केवल जावा 1.5 में पेश किया गया था ... उपयोग-मामलों को संभालने के लिए जो Runnable समर्थित नहीं है। सिद्धांत रूप में, जावा टीम Runnable.run() विधि के हस्ताक्षर को बदल सकती थी, लेकिन इससे प्री-1.5 कोड के साथ बाइनरी संगतता टूट गई होगी, पुराने जावा कोड को नए जेवीएम में माइग्रेट करते समय रिकोडिंग की आवश्यकता होती है। वह एक बड़ा नो-नो है। जावा पीछे की ओर संगत होने का प्रयास करता है ... और यह व्यवसाय कंप्यूटिंग के लिए जावा के सबसे बड़े बिकने वाले बिंदुओं में से एक रहा है।

और जाहिर है, ऐसे उपयोग-मामले हैं जहां किसी कार्य को परिणाम वापस करने या चेक अपवाद फेंकने की आवश्यकता नहीं होती है। उन उपयोग-मामलों के लिए, Runnable का उपयोग Callable<Void> और call() विधि से एक डमी ( null ) मान लौटने से अधिक संक्षिप्त है।

जावा में समवर्ती धागे को डिज़ाइन करते समय रननेबल और कॉल करने योग्य इंटरफेस का उपयोग करने के बीच क्या अंतर है, आप दूसरे पर एक क्यों चुनेंगे?


आइए देखते हैं कि कोई रननेबल और कॉल करने योग्य कहां उपयोग करेगा।

चलने योग्य और कॉल करने योग्य दोनों कॉलिंग थ्रेड की तुलना में एक अलग थ्रेड पर चलते हैं। लेकिन कॉल करने योग्य एक मूल्य वापस कर सकता है और रननेबल नहीं कर सकता है। तो यह वास्तव में कहां लागू होता है।

रननेबल : यदि आपके पास आग है और कार्य भूल जाते हैं तो रननेबल का उपयोग करें। अपना कोड एक रननेबल के अंदर रखें और जब रन () विधि कहा जाता है, तो आप अपना कार्य कर सकते हैं। जब आप अपना कार्य करते हैं तो कॉलिंग थ्रेड वास्तव में परवाह नहीं करता है।

कॉल करने योग्य : यदि आप किसी कार्य से मूल्य पुनर्प्राप्त करने का प्रयास कर रहे हैं, तो कॉल करने योग्य का उपयोग करें। अब अपने आप को कॉल करने योग्य नौकरी नहीं करेगा। आपको भविष्य की आवश्यकता होगी कि आप अपने कॉलबल के चारों ओर लपेटें और भविष्य में अपने मूल्य प्राप्त करें .get ()। यहां कॉलिंग थ्रेड को अवरुद्ध कर दिया जाएगा जब तक भविष्य भविष्य के साथ वापस न आएगा जो बदले में कॉल करने योग्य कॉल () विधि को निष्पादित करने की प्रतीक्षा कर रहा है।

तो एक लक्ष्य वर्ग के लिए एक इंटरफ़ेस के बारे में सोचें जहां आपके पास चलाने योग्य और कॉल करने योग्य दोनों विधियों को परिभाषित किया गया है। कॉलिंग क्लास यादृच्छिक रूप से आपके इंटरफ़ेस विधियों को कॉल करेगी जो यह नहीं जानती कि कौन सा रननेबल है और कौन कॉल करने योग्य है। एक कॉल करने योग्य विधि कहने तक चलने योग्य विधियां असीमित रूप से निष्पादित होंगी। यहां कॉलिंग क्लास का थ्रेड ब्लॉक होगा क्योंकि आप अपनी लक्षित कक्षा से मूल्य पुनर्प्राप्त कर रहे हैं।

नोट: अपनी लक्षित कक्षा के अंदर आप एक थ्रेड निष्पादक पर कॉल करने योग्य और रननेबल को कॉल कर सकते हैं, जिससे यह तंत्र एक धारावाहिक प्रेषण कतार के समान बना सकता है। इसलिए जब तक कॉलर आपके रननेबल रैप किए गए तरीकों को कॉल करता है तब तक कॉलिंग थ्रेड अवरुद्ध किए बिना वास्तव में तेज़ी से निष्पादित होगा। जैसे ही यह भविष्य विधि में लिपटे कॉलबल को कॉल करता है, उसे तब तक अवरुद्ध करना होगा जब तक कि अन्य सभी कतारबद्ध वस्तुओं को निष्पादित नहीं किया जाता है। केवल तभी विधि मूल्यों के साथ वापस आ जाएगी। यह एक सिंक्रनाइज़ेशन तंत्र है।


जैसा कि पहले से ही उल्लेख किया गया था कॉलबल अपेक्षाकृत नया इंटरफ़ेस है और इसे समवर्ती पैकेज के हिस्से के रूप में पेश किया गया था। कॉलबल और रननेबल दोनों को निष्पादकों के साथ इस्तेमाल किया जा सकता है। क्लास थ्रेड (जो खुद को रननेबल लागू करता है) केवल रननेबल का समर्थन करता है।

आप अभी भी निष्पादकों के साथ रननेबल का उपयोग कर सकते हैं। कॉल करने योग्य का लाभ यह है कि आप इसे निष्पादक को भेज सकते हैं और तुरंत वापस परिणाम प्राप्त कर सकते हैं जिसे निष्पादन समाप्त होने पर अपडेट किया जाएगा। इसे रननेबल के साथ लागू किया जा सकता है, लेकिन इस मामले में आपको खुद को परिणाम प्रबंधित करना होगा। उदाहरण के लिए आप परिणाम कतार बना सकते हैं जो सभी परिणामों को पकड़ लेगा। अन्य धागे इस कतार पर इंतजार कर सकते हैं और आने वाले परिणामों से निपट सकते हैं।


मैंने इसे एक और ब्लॉग में पाया जो इसे इन differences थोड़ा और समझा सकता है:

हालांकि दोनों इंटरफेस उन वर्गों द्वारा लागू किए जाते हैं जो निष्पादन के एक अलग धागे में निष्पादित करना चाहते हैं, लेकिन दोनों इंटरफ़ेस के बीच कुछ अंतर हैं:

  • एक Callable<V> उदाहरण प्रकार V का परिणाम देता है, जबकि एक Runnable इंस्टेंस नहीं करता है।
  • एक Callable<V> इंस्टेंस चेक अपवाद फेंक सकता है, जबकि एक Runnable इंस्टेंस नहीं कर सकता है

जावा के डिजाइनरों को Runnable इंटरफ़ेस की क्षमताओं को विस्तारित करने की आवश्यकता महसूस हुई, लेकिन वे Runnable इंटरफ़ेस के उपयोग को प्रभावित नहीं करना चाहते थे और शायद यही वजह है कि वे जावा 1.5 में Callable नामक एक अलग इंटरफेस के लिए गए थे पहले से ही मौजूदा Runnable बदल रहा है।


call() इंटरफ़ेस call() विधि घोषित करता है और आपको जेनेरिक प्रदान करने की आवश्यकता होती है क्योंकि ऑब्जेक्ट कॉल () को वापस करना चाहिए -

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

दूसरी ओर चलने योग्य इंटरफ़ेस है जो run() विधि घोषित करता है जिसे आप रननेबल के साथ थ्रेड बनाते हैं और उस पर कॉल प्रारंभ () कहते हैं। आप सीधे रन () को भी कॉल कर सकते हैं, लेकिन यह केवल रन () विधि को निष्पादित करता है, वही धागा है।

public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used 
     * to create a thread, starting the thread causes the object's 
     * <code>run</code> method to be called in that separately executing 
     * thread. 
     * <p>
     * The general contract of the method <code>run</code> is that it may 
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

संक्षेप में कुछ उल्लेखनीय अंतर हैं

  1. एक Runnable ऑब्जेक्ट परिणाम नहीं देता है जबकि एक Callable ऑब्जेक्ट परिणाम देता है।
  2. एक Runnable ऑब्जेक्ट एक चेक अपवाद फेंक नहीं सकता है, एक Runnable ऑब्जेक्ट अपवाद फेंक सकता है।
  3. Runnable इंटरफेस जावा 1.0 के आसपास रहा है जबकि Callable केवल जावा 1.5 में पेश किया गया था।

कुछ समानताओं में शामिल हैं

  1. रननेबल या कॉल करने योग्य इंटरफेस को लागू करने वाले वर्गों के उदाहरण संभावित रूप से किसी अन्य थ्रेड द्वारा निष्पादित किए जाते हैं।
  2. कॉल करने योग्य और रननेबल इंटरफेस दोनों का इंस्टॉलेशन execorService द्वारा सबमिट () विधि के माध्यम से निष्पादित किया जा सकता है।
  3. दोनों कार्यात्मक इंटरफेस हैं और जावा 8 के बाद लैम्ब्डा अभिव्यक्तियों में उपयोग किए जा सकते हैं।

निष्पादक सेवा इंटरफेस में तरीके हैं

<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);

कॉल करने योग्य और रननेबल के बीच का अंतर निम्न है:

  1. कॉल करने योग्य जेडीके 5.0 में पेश किया गया है लेकिन जेएनके 1.0 में रननेबल पेश किया गया है
  2. कॉल करने योग्य कॉल () विधि है लेकिन रननेबल चलाने () विधि है।
  3. कॉल करने योग्य कॉल विधि है जो मान देता है लेकिन रननेबल में चलने वाली विधि है जो किसी भी मान को वापस नहीं करती है।
  4. कॉल विधि चेक अपवाद फेंक सकता है लेकिन रन विधि चेक अपवाद फेंक नहीं सकता है।
  5. कार्य कतार में रखने के लिए कॉल करने योग्य उपयोग सबमिट () विधि लेकिन कार्य कतार में रखने के लिए रननेबल उपयोग निष्पादित () विधि।

  • call() करने योग्य को call() विधि को लागू करने की आवश्यकता होती है जबकि Runnable को run() विधि को लागू करने की आवश्यकता होती है।
  • एक Callable एक मूल्य वापस कर सकता है लेकिन एक Runnable नहीं कर सकता है।
  • एक Callable चेक अपवाद फेंक सकता है लेकिन एक Runnable नहीं कर सकता है।
  • ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) विधियों के साथ एक ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) उपयोग किया जा सकता है लेकिन एक Runnable नहीं हो सकता है।

    public interface Runnable {
        void run();
    }
    
    public interface Callable<V> {
        V call() throws Exception;
    }
    




callable