2012-05-01 17 views
58

पारंपरिक प्रतीक्षा सूचना तंत्र पर हालत इंटरफ़ेस/कार्यान्वयन का उपयोग करने का क्या फायदा है? यहाँ मैं टिप्पणी डौग ली द्वारा लिखित बोली: बाहर वस्तु पर नजर रखने के तरीके (प्रतीक्षा करें, को सूचित करें और notifyAll) अलग वस्तुओं मेंहालत बनाम तंत्र को सूचित करने की प्रतीक्षा करें

स्थिति कारकों उन लोगों के साथ संयोजन के द्वारा, वस्तु प्रति एकाधिक इंतजार सेट होने का प्रभाव देने के लिए मनमाने ढंग से लॉक कार्यान्वयन का उपयोग। जहां लॉक सिंक्रनाइज़ किए गए तरीकों और कथन के उपयोग को प्रतिस्थापित करता है, एक शर्त ऑब्जेक्ट मॉनीटर विधियों के उपयोग को प्रतिस्थापित करती है।

मुझे लगता है कि यह इंतजार/सूचना तंत्र को लागू करने का एक और ऑब्जेक्ट ओरिएंटेड तरीका है। लेकिन क्या पूर्व में एक अच्छा फायदा है?

उत्तर

19

कई फायदे तरह से ऊपर के बारे में स्थिति इंटरफ़ेस कुछ महत्वपूर्ण है, उसका उल्लेख कर रहे हैं इस प्रकार है:

स्थिति इंटरफेसदो अतिरिक्त तरीकों हैं कि साथ आता है:

1) बूलियन awaitUntil (दिनांक समय सीमा) फेंकता InterruptedException: जब तक यह संकेत या बाधित है, या निर्दिष्ट समय सीमा समाप्त होने के इंतजार करने की वर्तमान धागा कारण।

2) awaitUninterruptibly(): जब तक यह संकेत है प्रतीक्षा करने के लिए वर्तमान धागा कारण।

यदि वर्तमान थ्रेड की बाधित स्थिति सेट की जाती है तो यह इस विधि में प्रवेश करती है, या प्रतीक्षा करते समय बाधित होती है, यह संकेतित होने तक प्रतीक्षा जारी रखेगी। जब यह अंततः इस विधि से वापस आता है तो इसकी बाधित स्थिति अभी भी सेट की जाएगी।

उपरोक्त दो विधियां डिफ़ॉल्ट मॉनिटर में मौजूद नहीं हैं जो कि ऑब्जेक्ट क्लास में है, कुछ स्थितियों में हम थ्रेड के लिए समय सीमा तय करना चाहते हैं, तो हम कंडीशन इंटरफ़ेस द्वारा ऐसा करने में सक्षम हैं।

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

अधिक जानकारी स्थिति इंटरफ़ेस जावा प्रलेखन के लिए:

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil%28java.util.Date%29

+1

सिस्टम घड़ी में परिवर्तन होने पर प्रतीक्षा (दिनांक की समयसीमा) का व्यवहार बदल जाएगा, जबकि यह प्रतीक्षा के लिए नहीं हो सकता है (लंबे समय में InMilliseconds) –

27

सबसे बड़ी समस्या यह है कि प्रतीक्षा करें/सूचित करें नए डेवलपर्स के लिए त्रुटि प्रवण है। मुख्य समस्या यह नहीं जानती कि उन्हें सही तरीके से कैसे संभालना है परिणामस्वरूप अस्पष्ट बग है।

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

स्थिति एक समर्पित घटक में इस कार्यक्षमता ऊपर लपेटता, लेकिन यह ज्यादा एक ही व्यवहार करती है।

प्रतीक्षा/nofity इस एक और कई मिनट पहले पोस्ट के बारे में एक सवाल है, कई नहीं है अधिक Search [java]+wait+notify

+0

आपके उत्तर के लिए धन्यवाद, क्लास/इंटरफेस के लेखक का मतलब है "प्रति ऑब्जेक्ट एकाधिक प्रतीक्षा-सेट रखने के प्रभाव को देने के लिए"? – 100pipers

+2

आपके पास एक ही लॉक साझा करने वाली कई स्थितियां हो सकती हैं। जैसे http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html प्रतीक्षा करें/सूचित करें केवल एक "प्रतीक्षा सेट" है यानी आप केवल किसी भी वेटर को सूचित कर सकते हैं, विशिष्ट नहीं समूह। –

+4

मुझे यकीन नहीं है कि हालत किसी तीसरे बिंदु के साथ कैसे मदद करती है।प्रतीक्षा करने से पहले बुलाए जाने पर संकेतों को कॉल खो दिया जाता है, इंतजार अभी भी जल्दी वापस आ सकता है, इंटरफ़ेस में कुछ भी इंगित करता है कि राज्य को बदलना है। –

26

जब आप का उपयोग Condition: await()/signal() आप भेद कर सकते हैं जो वस्तु या वस्तुओं के समूह/धागे एक विशिष्ट संकेत मिलता है। यहाँ एक छोटी उदाहरण है जहां कुछ धागे, उत्पादकों, isEmpty संकेत मिल जाएगा, जबकि उपभोक्ताओं isFull संकेत मिल जाएगा:

private volatile boolean usedData = true;//mutex for data 
private final Lock lock = new ReentrantLock(); 
private final Condition isEmpty = lock.newCondition(); 
private final Condition isFull = lock.newCondition(); 

public void setData(int data) throws InterruptedException { 
    lock.lock(); 
    try { 
     while(!usedData) {//wait for data to be used 
      isEmpty.await(); 
     } 
     this.data = data; 
     isFull.signal();//broadcast that the data is now full. 
     usedData = false;//tell others I created new data.   
    }finally { 
     lock.unlock();//interrupt or not, release lock 
    }  
} 

public void getData() throws InterruptedException{ 
    lock.lock(); 
    try { 
     while(usedData) {//usedData is lingo for empty 
      isFull.await(); 
     } 
     isEmpty.signal();//tell the producers to produce some more. 
     usedData = true;//tell others I have used the data. 
    }finally {//interrupted or not, always release lock 
     lock.unlock(); 
    }  
} 
+0

- धन्यवाद, मैं http://stackoverflow.com/questions/10407708/signalall-in पोस्ट करने के बाद आपकी पोस्ट के माध्यम से गया -कंडिशन-इंटरफेस-बनाम-नोटिफाइल-इन-ऑब्जेक्ट – 100pipers

+0

शानदार उदाहरण! क्या आप सिग्नलिंग से पहले इस्तेमाल नहीं कर सकते हैंडेटा = सच/झूठा? – AfterWorkGuinness

+0

जब आप प्रतीक्षा()/सूचित करें() का उपयोग करते हैं तो आप यह तय नहीं करते कि कौन सी प्रतीक्षा वस्तुओं/धागे अधिसूचित हैं: आप करते हैं। –

0

@AfterWorkGuinness

आप usedData = सही/गलत स्थापित कर नहीं करना चाहिए संकेत

संकेत के बाद से पहले कोड लॉक ब्लॉक के अंत तक जाएं और इसे छोड़ दें, इसलिए ऑर्डर कोई फर्क नहीं पड़ता

1

विशेष रूप से समाधान करने के लिए क्यों कई waitsets होने एक फायदा है:

प्रतीक्षा के साथ

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

लेकिन सूचित करें सभी कॉल प्रत्येक कॉल के साथ मंथन करते हैं, जहां हर धागा जागता है और ताला के लिए संघर्ष करता है, लेकिन केवल कोई प्रगति कर सकता है। अन्य धागे सभी लॉक के लिए चारों ओर घूमते हैं, एक बार में, वे लॉक प्राप्त कर सकते हैं और अधिकतर प्रतीक्षा करने के लिए वापस जाते हैं। यह बहुत अधिक लाभ के लिए बहुत अधिक विवाद उत्पन्न करता है, यह अधिसूचना का उपयोग करने में सक्षम होना बेहतर होगा और केवल एक धागा अधिसूचित किया जाना चाहिए, जहां अधिसूचना उस धागे से प्रासंगिक है।

यह वह जगह है जहां प्रतीक्षा करने के लिए अलग-अलग स्थितियां एक बड़ी सुधार है। कतार एक शर्त पर सिग्नल का आह्वान कर सकती है और पता है कि यह केवल एक धागा जगाएगा, जहां वह धागा विशेष रूप से इस स्थिति की प्रतीक्षा कर रहा है।

API doc for Condition एक कोड उदाहरण है कि एक घिरे बफर के लिए कई शर्तों का उपयोग से पता चलता है, यह कहते हैं:

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

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