थ्रेड एक अमूर्त वर्ग क्यों नहीं है और शुरू () अंतिम नहीं है?


79

क्यों Threadवर्ग को एक नियमित वर्ग के रूप में लागू किया गया था न कि अमूर्त वर्ग के साथ run()विधि को अमूर्त किया गया था।

क्या यह संभवतः किसी समस्या का परिचय देगा? या इस तरह से होने में इसका कोई उपयोग है?

इसके अलावा, Thread.start()विधि को एक बहुत विशिष्ट विधि माना जाता है जिसकी कार्यक्षमता किसी अन्य वर्ग द्वारा लागू नहीं की जा सकती है (यदि मैं गलत नहीं हूं)। और इसलिए मुझे लगता है कि यह finalकीवर्ड किसी अन्य विधि से अधिक के लिए उपयुक्त होगा।

लेकिन मैं इस विधि को ओवरराइड करने और इसका उपयोग करने में सक्षम हूं जैसा मैं चाहता हूं,

public class Test extends Thread {
    public static void main (String... args) {
        Thread test = new Test();
        test.start();
    }

    @Override
    public void run() {
        System.out.println("New thread started...");
    }

    @Override
    public void start() {
        System.out.println("Did anyone tell you I will spawn a new thread??");
    }
}

यह स्पष्ट रूप से केवल मुद्रित,

क्या किसी ने तुमसे कहा था कि मैं एक नया धागा फूँक दूंगा ??

क्या इंजीनियर की जगह आपको भ्रमित करने के अलावा अन्य का उपयोग करने में कोई फायदा है?

यदि नहीं, तो थ्रेड क्लास में विधि को अंतिम घोषित क्यों नहीं किया गया?


यहाँ आप विधि को कक्षा के एक सदस्य के रूप में शुरू कर रहे हैं ... इसके अनुसूचक से नहीं बुलाया गया ...
कोडरनेजी

2
केवल स्पष्टता के लिए - आप पूछ रहे हैं कि क्यों थ्रेड.रून () सार नहीं है, क्योंकि उपयोगकर्ताओं को इसे ओवरराइड करने की आवश्यकता है, और थ्रेड.स्टार्ट () अंतिम नहीं है, क्योंकि इसे ओवरराइड करने का कोई मतलब नहीं है? अच्छा प्रश्न! मैंने देखा कि किसी ने नीचा दिखाया है - मुझे आश्चर्य है कि क्यों?
निक

3
मैं चाहता हूं कि Threadकक्षा अंतिम थी। कंस्ट्रक्टर पहले से ही एक रनवेबल लेता है, इसलिए एक धागा बनाने के लिए वंशानुक्रम की आवश्यकता नहीं होती है।
8

जवाबों:


50

क्यों थ्रेड क्लास को एक नियमित वर्ग के रूप में लागू किया गया था और न कि रन () पद्धति के साथ एक अमूर्त वर्ग था।

यह प्रश्न वास्तव में इस तथ्य को उबालता है कि आपको हमेशा विरासत पर रचना पसंद करनी चाहिए।

यदि Threadवर्ग के रूप में घोषित किया गया था abstract, तो भाषा को एक और वर्ग प्रदान करना होगा जो उससे विस्तारित हो जिसे प्रोग्रामर एक बनाने के लिए उपयोग कर सकते हैं Thread। आपका प्रश्न तो के बारे में होगा क्यों इस वर्ग कि extendsसे Threadनहीं है abstract। यदि भाषा ने एक और वर्ग प्रदान नहीं किया extendsहै Thread, तो प्रोग्रामर को अपना स्वयं का वर्ग बनाना होगा जो कि विधि extendसे Threadआये और ओवरराइड करे run()

यदि नहीं, तो थ्रेड क्लास में विधि को अंतिम घोषित क्यों नहीं किया गया ??

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

अगर जावा को आज स्क्रैच से फिर से डिजाइन किया गया, तो एक अच्छा मौका है कि डिजाइन अलग होगा


1
यद्यपि आपको नामकरण के लिए थ्रेड क्लास का विस्तार करने की आवश्यकता नहीं है (बस थ्रेडसेटसेट () कॉलिंग थ्रेड), जो यह समझाता है कि क्लास एब्सट्रैक्ट क्यों नहीं हो सकता है ...
कोडबेंडर

@ कोडबेंडर सहमत। मैंने अपने उत्तर से हटा दिया है क्योंकि यह एक अच्छा उदाहरण नहीं था और इसलिए भी कि आपके प्रश्न ने यह नहीं पूछा कि थ्रेड को कब बढ़ाया जाए
CKing

यह एक साफ डिजाइन है; आज यह अलग क्यों होगा?
वॉरेन ड्यू

76

आप बेशक अपने आप को पैर में गोली मारना चुन सकते हैं, लेकिन इसका मतलब यह नहीं है कि आपको चाहिए।

क्यों थ्रेड क्लास को एक नियमित वर्ग के रूप में लागू किया गया था और न कि रन () पद्धति के साथ एक अमूर्त वर्ग था।

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

Runnable r = new Runnable() {
    @Override
    public void run() {
        ...
    }
};
Thread t = new Thread(r);
t.start();

और इसलिए मुझे लगता है कि अंतिम कीवर्ड किसी भी अन्य विधि से अधिक के लिए उपयुक्त होगा।

हां और ना। आप अपने स्वयं के कार्यान्वयन द्वारा प्रारंभ () को प्रतिस्थापित नहीं कर सकते, लेकिन यदि आप चाहें तो आप प्रारंभ में अतिरिक्त कार्य कर सकते हैं:

@Override
public void start() {
    System.out.println("Did anyone tell you I will spawn a new thread??");
    super.start();
}

उस ने कहा, अगर जावा को आज खरोंच से फिर से डिजाइन किया गया था, तो एक अच्छा मौका है कि डिजाइन अलग होगा। याद रखें कि यह वर्ग जावा 1.0 से है, और अभी भी पिछड़ा-संगत है।


मैंने अपने उत्तर में आपको उद्धृत किया है। आशा है कि आपके साथ ठीक है :)
CKing

11
कोई दिक्कत नहीं है। यह खुला-स्रोत है।
जेबी निज़ेट

2
@NayukiMinase नं। भाषा में अंतर हमेशा से रहे हैं। JDK 1.0 के बाद से चलाने योग्य मौजूद है।
जेबी निज़ेट

ओह, मैं इस बात से भ्रमित हो गया कि इंटरफ़ेस कॉलबैक (पद्धति के ओवरराइड करने के बजाय) के आधार पर एक नया AWT इवेंट-हैंडलिंग सिस्टम 1.1 में कैसे पेश किया गया था।
नायुकी

1
धागे में एक साफ डिजाइन है; आज कोई अलग क्यों होगा?
वॉरेन ड्यू

40

क्यों Thread.start()नहीं है final?

क्या आप वाकई इसे ओवरराइड नहीं करना चाहेंगे?

Class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r) {
            @Override
            public void start() {
                LOGGER.info("Starting thread " + this);
                super.start();
            }
        };
    }
}

0

मुझे लगता है कि उत्तर के लिए कुछ कैलीफ़ेरेशन पोस्ट किए जाने चाहिए:

"क्या आप वाकई इसे ओवरराइड नहीं करना चाहेंगे?"

नहीं ! मैं नहीं। यह कहते हुए, "क्या आप निश्चित हैं, आप इस चर को निजी घोषित करना चाहते हैं?" क्योंकि अगर मैं बिना किसी डर के सार्वजनिक रूप से उपयोग किए जाने वाले किसी भी वैरिएबल की घोषणा कर सकता हूं, तो अन्य डेवलपर्स मेरे डिजाइन तर्क को गड़बड़ कर सकते हैं, कोडिंग एक हवा होगी। स्कोप, अमूर्तता, बहुरूपता, त्रुटि से निपटने आदि की OOPS अवधारणाओं का एक सबसे महत्वपूर्ण उद्देश्य अन्य डेवलपर्स को आपके कोड के पीछे के डिजाइन और इरादों के बारे में बताना है। प्रश्न में बताया गया है, जब आपने प्रारंभ विधि को ओवरराइड किया था, तो कोई भी आपको मजबूर नहीं कर रहा है। सुपरस्टार्ट () का उपयोग करने के लिए। @ कोडबेंडर ने सुपर के बिना थ्रेड () और कंपाइलर का उपयोग किए बिना कभी भी शिकायत नहीं की। तो वह थ्रेडिंग के पूरे तंत्र को तोड़ने के लिए स्वतंत्र है और संकलक को केवल इसे पारित करने के लिए माना जाता है? थ्रेड की प्रारंभ विधि यह सुनिश्चित करती है कि रन विधि कहा जाता है और सही समय पर निष्पादित होता है! यह थ्रेडिंग की अवधारणा के लिए महत्वपूर्ण है। मैं सही होने से ज्यादा खुश रहूंगा, अगर मैं यहां कुछ याद करता हूं। २।

क्योंकि एक धागा बनाने के लिए अनुशंसित तरीका थ्रेड को उप-वर्ग के लिए नहीं है।

ठीक है, अगर कोडबेंडर को डिज़ाइन द्वारा अनुमति दी जाती है, थ्रेड को सब्स्क्राइब करने और प्रारंभ विधि को गड़बड़ करने के लिए, उस तर्क से, यह पैर में ही डिजाइन की शूटिंग है। किए गए एक अन्य बयान द्वारा, (जो मैं पूरी तरह से सहमत हूं), रननेबल अनुशंसित तरीका है। फिर हम सभी को बिना किसी प्रतिबंध के थ्रेड को तुरंत थ्रेड करने की अनुमति क्यों देते हैं? यह निम्नलिखित है:

आप अपने स्वयं के कार्यान्वयन द्वारा प्रारंभ () के कार्यान्वयन को प्रतिस्थापित नहीं कर सकते,

यह वास्तव में कोडबेंडर के दावे का समर्थन करता है कि जब आप कहते हैं कि प्रारंभ विधि अंतिम होनी चाहिए .. ^

एक बिंदु, जो वैध है, पहले से ही एक साइड नोट के रूप में उल्लिखित है, लेकिन वास्तविक उत्तर है इस प्रश्न है

"अनिच्छुक अनुकूलता"।

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

फिर, मैं सही होने से ज्यादा खुश रहूंगा, अगर मैं कुछ चूक गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.