मुझे पता है कि यह अब तक एक पुराना सवाल है, लेकिन प्रश्न और उत्तर पढ़ने के बाद मैं अपने स्वयं की मदद नहीं कर सका, मुझे आशा है कि आपको यह उपयोगी लगेगा।
पता चल सके कि कतार वास्तव में पूर्ण या खाली कुछ अन्य इंतजार कर रहे धागे को अधिसूचित करने से पहले, आप भूल रहे हैं जो है दोनों तरीकों put (T t)
और T get()
दोनों synchronized
तरीके हैं, जिसका अर्थ है कि केवल एक धागा एक पर इन तरीकों में से एक में प्रवेश कर सकते है के बारे में समय, फिर भी यह उन्हें एक साथ काम करने से नहीं रोकेगा, इसलिए यदि कोई थ्रेड-ए put (T t)
विधि दर्ज कर चुका है तो कोई अन्य थ्रेड-बी अभी भी दर्ज हो सकता है और थ्रेड से पहले T get()
विधि में निर्देशों को निष्पादित करना प्रारंभ कर सकता है- put (T t)
से बाहर निकला है, और इसलिए यह double-checking
डिज़ाइन डेवलपर को थोड़ी अधिक सुरक्षित महसूस कर देगा क्योंकि आप नहीं जानते कि भविष्य में सीपीयू संदर्भ स्विचिंग अगर होगा या कब होगा। मैं इस दृष्टिकोण वहाँ double checking
की आवश्यकता नहीं है का उपयोग करते हुए इस link
Condition isFullCondition;
Condition isEmptyCondition;
Lock lock;
public BQueue() {
this(Integer.MAX_VALUE);
}
public BQueue(int limit) {
this.limit = limit;
lock = new ReentrantLock();
isFullCondition = lock.newCondition();
isEmptyCondition = lock.newCondition();
}
public void put (T t) {
lock.lock();
try {
while (isFull()) {
try {
isFullCondition.await();
} catch (InterruptedException ex) {}
}
q.add(t);
isEmptyCondition.signalAll();
} finally {
lock.unlock();
}
}
public T get() {
T t = null;
lock.lock();
try {
while (isEmpty()) {
try {
isEmptyCondition.await();
} catch (InterruptedException ex) {}
}
t = q.poll();
isFullCondition.signalAll();
} finally {
lock.unlock();
}
return t;
}
से स्रोत कोड संपादित कर लिया है //
,:
एक बेहतर और एक अधिक सिफारिश की दृष्टिकोण Reentrant Locks
और Conditions
उपयोग करने के लिए है क्योंकि lock
ऑब्जेक्ट को दो विधियों के बीच साझा किया जाता है, जिसका अर्थ है कि केवल एक थ्रेड ए या बी सिंक्रनाइज़ किए गए तरीकों के विपरीत एक समय में इन तरीकों में से किसी एक को दर्ज कर सकता है जो विभिन्न मॉनीटर बनाता है, और केवल उन थ्रेड प्रतीक्षा कर रहे हैं क्योंकि कतार पूर्ण है, वहां और जगह है, और वही थ्रेड के लिए जाता है क्योंकि कतार खाली है, इससे बेहतर सीपीयू उपयोग होता है। आप स्रोत कोड here
स्रोत
2014-09-14 23:01:55
समस्या का एक हिस्सा समवर्ती कार्यक्रमों में 'प्रतीक्षा' और 'सूचित करें 'का उपयोग करने में कठिनाई से संबंधित समस्या का हिस्सा अधिक विस्तृत उदाहरण पा सकते हैं; जोशुआ ब्लोच को उद्धृत करने के लिए, वे समवर्ती प्रोग्रामिंग के निम्न स्तर (असेंबली भाषा) की तरह हैं। " वह 'NotifyAll' का उपयोग करने की वकालत करता है और प्रतीक्षा करते समय थ्रेड को हमेशा एक लूप के भीतर चेक करना चाहिए ताकि वे आवश्यकतानुसार प्रतीक्षा कर सकें। वास्तव में, आपको बस प्रतीक्षा/अधिसूचना का उपयोग नहीं करना चाहिए और इसके बजाय हमेशा जावा एसई 5 में प्रदान किए गए उच्च स्तरीय समवर्ती एपीआई का उपयोग करने की योजना बनाना चाहिए। धागे की बजाय और प्रतीक्षा/सूचित करें, कार्य और निष्पादकों के संदर्भ में समवर्ती ऐप्स डिज़ाइन करें। – scottb
हाँ, मैं पूरी तरह से आपसे सहमत हूं, बूढ़े लेकिन उपहार: पहिया का पुन: आविष्कार करने की कोई आवश्यकता नहीं है। लेकिन बस सोचें कि हमें इस मामले के लिए प्रतीक्षा और अधिसूचना का उपयोग करने की आवश्यकता है। मुझे पता है कि प्रतीक्षा() को लूप के भीतर इस्तेमाल किया जाना चाहिए, सभी javadocs (नकली wakeups) में समझाया गया है: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait (लंबा)। लेकिन अधिसूचनाओं के लिए उन शर्तों के बारे में हैक क्या है? यही वह बिंदु है जिसे मैं नहीं मिला। – tugcem
देखें [यहां] (http://fuseyism.com/classpath/doc/java/util/concurrent/LinkedBlockingQueue-source.html) - वे 'पुनर्वित्त लॉक' और 'कंडीशन' का उपयोग करते हैं, 'प्रतीक्षा नहीं'/'सूचित करें ' बिलकुल। – OldCurmudgeon