2011-11-22 12 views
5

मेरे पास एक साधारण वर्ग है जो अपने स्वयं के धागे में कुछ गणना करता है और परिणामों को श्रोता को रिपोर्ट करता है।जावा - क्या मुझे अपने साझा श्रोता सदस्य चर को अस्थिर घोषित करना है?

class Calculator extends Thread { 
    protected Listener listener; 

    public void setListener(Listener l) { 
     listener = l; 
    } 

    public void run() { 
     while (running) { 
      ... do something ... 

      Listener l = listener; 

      if (l != null) { 
       l.onEvent(...); 
      } 
     } 
    } 
} 

किसी भी समय, उपयोगकर्ता अगर वह एक निश्चित समय अवधि के लिए कोई ईवेंट नहीं चाहता है setListener (शून्य) कॉल कर सकते हैं। तो, रन() समारोह में, मैं श्रोता की एक प्रतिलिपि बनाने, तो मैं एक NullPointerException जो श्रोता के बाद अशक्त करने के लिए सेट है, तो हो सकता है में चलाने नहीं कर सकता! = अशक्त हालत की जांच सफल रहा । मेरे मामले में, मेरा मानना ​​है कि यह सिंक्रनाइज़ करने के लिए यह एक सही विकल्प है।

मेरा प्रश्न है: क्या मुझे यहां श्रोता सदस्य चर को अस्थिर घोषित करना चाहिए? मैं अस्थिर के बारे में बहुत कुछ पढ़ रहा हूं, लेकिन सभी उदाहरण बुनियादी डेटा प्रकारों (बूलियन, int, ...) को लक्षित करते हैं, और ऑब्जेक्ट्स नहीं। इसलिए, मुझे यकीन नहीं है कि वस्तुओं को अस्थिर घोषित किया जाना चाहिए/नहीं। मेरा मानना ​​है कि मुझे इसे अस्थिर घोषित करना है, इसलिए थ्रेड में हमेशा सदस्य चर का नवीनतम संस्करण होता है, लेकिन मुझे यकीन नहीं है।

धन्यवाद!

+0

बस एक सुझाव के रूप में - वास्तव में आपके प्रश्न का उत्तर नहीं दे रहा है - लेकिन क्या यह आपके श्रोता पर 'सक्षम' प्रकार का ध्वज डालने के लिए बेहतर काम करेगा, और उसके बाद ग्राहक को श्रोता को शून्य या नल-शून्य सेट करने के बजाय बेहतर काम करेगा , क्या यह सेट किया गया है (सत्य) या सेट सक्षम (झूठा)? यह आपको एक अनजान एनपीई को संभालने की समस्या के आसपास आता है, और आपको समय-समय पर नए श्रोता वस्तुओं को तुरंत चालू करने से रोकता है। –

+0

@ जेपर डी।, यह वास्तव में, वास्तव में, वास्तव में बदसूरत समाधान है जो आप वहां पहुंचे हैं। – mre

+0

@ जिमकिली मैं आपके साथ सहमत हूं। हालांकि, मैं अपने प्रश्न को सरल बना रहा था, इसलिए यह थोड़ा अजीब लग रहा है। इसके लिए माफ़ी। –

उत्तर

5

हां। यह गारंटी देने के लिए कि Calculator थ्रेड एक नया मान देखता है, जो किसी अन्य थ्रेड द्वारा सेट किया गया है, आपको चर अस्थिर बनाना होगा।

हालांकि, volatile एक बहुत कम स्तर की तंत्र है और शायद ही कभी क्लाइंट कोड में उपयोग किया जाता है। मेरा सुझाव है कि आप इस परिदृश्य में java.util.concurrent.AtomicReference का उपयोग करने पर विचार करें, जो सुनिश्चित करता है कि ये चीजें अपेक्षित रूप से काम करती हैं।

+0

ठीक है, पुष्टि के लिए धन्यवाद। मैं परमाणु संदर्भ में देखूंगा, मुझे यह स्वीकार करना होगा कि मैंने नए समवर्ती पैकेज को बहुत लंबे समय तक अनदेखा कर दिया है। –

+0

हे .. मुझे भी, लेकिन ऐसा इसलिए है क्योंकि मैं यथासंभव लंबे समय तक समेकन से बचने की कोशिश करता हूं :-) – aioobe

+0

अच्छी सोच :) –

3

यदि आप इस दृष्टिकोण का उपयोग करते हैं, तो आप अब गारंटी नहीं दे सकते कि श्रोता setListener(null) रिटर्न के बाद कोई ईवेंट अधिसूचना प्राप्त नहीं करेगा। निष्पादन इस प्रकार आगे बढ़ना सकता है:

Listener l = listener; // listener != null at this point 

// setListener(null) executes here 

if (l != null) { 
    l.onEvent(...); 
} 

आप गारंटी के लिए है कि कोई घटनाओं, एक श्रोता के लिए तैनात किया जाएगा के बाद यह अपंजीकृत कर दिया गया है तो आप सिंक्रनाइज़ ब्लॉक उपयोग करने की आवश्यकता की जरूरत है। listener को volatile घोषित करने में सहायता नहीं होगी। कोड के बजाय होना चाहिए:

public synchronized void setListener(Listener l) { 
    listener = l; 
} 

public void run() { 
    while (running) { 
     ... do something ... 

     synchronized (this) { 
      if (listener != null) { 
       listener.onEvent(...); 
      } 
     } 
    } 
} 

आप हर समय synchronized की कीमत से बचना चाहते हैं, तो आप ऐसा कर सकते हैं:

if (listener != null) { 
    synchronized (this) { 
     if (listener != null) { 
      listener.onEvent(...); 
     } 
    } 
} 

यह मामूली जोखिम है कि आप के बाद एक घटना को याद करेंगे चलाता है एक गैर-शून्य श्रोता सेट करना। listener घोषित करने के लिए volatile शायद इसे ठीक कर देगा।

+0

यही कारण है कि मैं सदस्य चर की प्रतिलिपि बना रहा हूं। यदि सेट लिस्टनर (शून्य) कहा जाता है, तो स्थानीय चर एल को रन() में बदला नहीं जाता है। इस तरह, मैं सिंक्रनाइज़ेशन ब्लॉक से बचता हूं। नहीं? –

+0

@TedHopp, नहीं, क्योंकि वह सामग्री को स्थानीय चर में कॉपी करता है। – aioobe

+0

@JaperD। - मुझे एहसास हुआ और मेरे जवाब को पूरी तरह से संशोधित किया। –

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