प्रतीक्षा () और नींद () के बीच अंतर


1203

थ्रेड्स में wait()और क्या अंतर है sleep()?

क्या मेरी समझ यह है कि एक- wait()थिंग थ्रेड अभी भी चलन में है और सीपीयू चक्रों का उपयोग करता है लेकिन एक sleep()-िंग किसी भी सीपीयू चक्रों का सही उपभोग नहीं करता है?

हमारे पास दोनों क्यों हैं wait()और sleep(): उनका कार्यान्वयन निम्न स्तर पर कैसे भिन्न होता है?


50
बहुत अच्छा सवाल है। दोनों के शब्दार्थों को भ्रमित करना आसान है।
एंड्रियास पीटरसन

1
बहुत अच्छे प्रश्न हैं, लेकिन वे एक में 2 हैं। हमारे पास क्यों है दोनों समान नहीं हैं कि वे निचले स्तर पर कैसे लागू हो सकते हैं (और नहीं हैं!)। मैंने उसका भी उत्तर दिया है।
एस्टानी

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

1
यहाँ यह वर्णन करने वाला एक अच्छा लेख है: qat.com/use-waitnotify-instead-thread-sleep-java
Triton Man

3
इसके विपरीत - नींद "इसके सभी उपलब्ध सीपीयू-चक्रों का" उपयोग "करती है, लेकिन चूंकि धागा" प्रतीक्षा "में होगा - यदि आवश्यक हो तो इन का उत्पादन किया जा सकता है - वास्तव में अधिकांश ऑपरेटिंग सिस्टम स्वचालित रूप से चक्र का उत्पादन करते हैं यदि यह संभव है, इसलिए आपका थ्रेड कोई वास्तविक सीपीयू-लोड नहीं बनाएगा ... यह पुराने ऑपरेटिंग सिस्टम पर ऐसा करेगा, हालांकि। Object.wait (), दूसरी तरफ कभी भी किसी भी चक्र का उपयोग नहीं किया जाता है (क्योंकि किसी का ध्यान नहीं जाता) क्योंकि JVM द्वारा कार्यान्वित कई मामलों में सॉफ्टवेयर-इंटरप्ट के माध्यम से एहसास होता है - निजी, क्षणिक और पारदर्शी ताले। थ्रेड.स्लीप खराब अभ्यास है।
specializt

जवाबों:


837

A मॉनिटर पर waitदूसरे थ्रेड कॉलिंग द्वारा "वेक अप" किया जा सकता है notifyजिस पर प्रतीक्षा की जा रही है, जबकि ऐसा sleepनहीं हो सकता। मॉनिटर ऑब्जेक्ट पर एक ब्लॉक में भी wait(और notify) होना चाहिए, synchronizedजबकि sleepनहीं:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

इस बिंदु पर वर्तमान में थ्रेडिंग वेटिंग और मॉनिटर जारी करता है । एक और धागा हो सकता है

synchronized (mon) { mon.notify(); }

(एक ही monवस्तु पर) और पहला थ्रेड (मान लें कि यह मॉनीटर पर प्रतीक्षा करने वाला एकमात्र थ्रेड है) जाग जाएगा।

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

एक और बिंदु यह है कि आप खुद कॉल waitकरते Objectहैं (यानी आप किसी ऑब्जेक्ट के मॉनिटर पर प्रतीक्षा करते हैं) जबकि आप कॉल sleepकरते हैं Thread

फिर भी एक और बात यह है कि आप (जैसे कि थ्रेड जो बिना किसी स्पष्ट कारण के लिए फिर से शुरू हो रहा है) से शानदार वाट्सअप प्राप्त कर सकते हैं wait। आपको कुछ शर्त पर हमेशा waitकताई करनी चाहिए :

synchronized {
    while (!condition) { mon.wait(); }
}

131
नहीं ये नहीं हो सकता। इसे केवल बाधित किया जा सकता है।
पीटर attibraný

9
जब आप हस्तक्षेप कर रहे हैं, तो आपको पता होना चाहिए कि आप किस थ्रेड को बाधित करना चाहते हैं। जब आप सूचित कर रहे हैं, तो आपको बस ऑब्जेक्ट की आवश्यकता है, और यदि कोई अन्य धागा है जो इस ऑब्जेक्ट पर 'प्रतीक्षा' करता है, तो आपको परवाह नहीं है। प्रतीक्षा / सूचना का उपयोग संचार के लिए किया जाता है, जबकि नींद का उपयोग, अहम्, नींद के लिए किया जाता है।
पीटर attibraný

28
@ Geek - दुनिया में आप प्रतीक्षा क्यों करते हैं () सीपीयू साइकिल को बर्बाद करते हैं?
रॉबर्ट मुंटेनू

25
रुकावट को एक तंत्र के रूप में एक धागा को धीरे-धीरे पूरी तरह से चलाने से रोकने और शेष संचालन को रद्द करने के लिए प्रोत्साहित किया जाता है। wait/ notifyआमतौर पर किसी कार्य को पूरा करने के लिए किसी अन्य थ्रेड के लिए प्रतीक्षा करने के लिए या किसी निश्चित स्थिति के संतुष्ट होने तक प्रतीक्षा करने के लिए उपयोग किया जाता है।
लुइस वासरमैन

13
मैं सभी उत्तरों के माध्यम से पढ़ता हूं, हालांकि मुझे अभी भी लापता जानकारी का एक सा महसूस होता है। कई लोगों ने जावदोक से परिभाषाएँ लिखीं और दो अंग्रेजी शब्दों का अर्थ भी बताया लेकिन मैंने यह नहीं देखा कि मुझे प्रतीक्षा के बजाय कभी नींद क्यों लेनी चाहिए? दोनों के बीच बेंचमार्किंग और गति अंतर क्या है? अगर मैं वह सब कुछ कर सकता हूं जो मैं नींद से कर सकता हूं तो मुझे कभी भी नींद क्यों लेनी चाहिए?
बालाज़्स ज़ोल्डोस

334

एक प्रमुख अंतर जो अभी तक उल्लेख नहीं किया गया है वह यह है कि थ्रेड सोते समय अपने पास रखे ताले को जारी नहीं करता है , जबकि प्रतीक्षा करने पर उस ऑब्जेक्ट पर लॉक जारी होता wait()है जिसे कॉल किया जाता है।

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

105
प्रतीक्षा केवल उस ऑब्जेक्ट के लिए लॉक जारी करती है जिसे आप प्रतीक्षा () कहते हैं । यह किसी भी अन्य ताले जारी नहीं करता है ।
जॉन स्कीट

16
आपको वास्तव में एक ताले के भीतर से नींद को कॉल करने की आवश्यकता नहीं है - ताले और प्रतीक्षा करें / सूचित करें हाथ में हाथ लेकिन ताले और नींद असंबंधित हैं।
oxbow_lakes 7:24 पर

7
@oxbow_lakes - मैं कहूंगा कि आपको ताले के साथ नहीं सोना चाहिए, इसके लिए कुछ उपयोग मामले हैं। बस मतभेदों को इंगित करना चाहता था।
रॉबर्ट मुंटेनू

5
@RobertMunteanu, आपका उत्तर भ्रामक रूप से दावा करता है कि जावा लॉक sleepरखता है , लेकिन यह नहीं है। उचित तुलना करने के लिए, हम तुलना करेंगे और हम देख सकते हैं कि दोनों निर्देश जारी नहीं करते हैं । यदि कोई अंतर है, तो हम कह सकते हैं कि स्पष्ट रूप से जावा लॉक का उपयोग नहीं किया जाता है , लेकिन सवाल बोली के बारे में पूछ रहा है "उनका कार्यान्वयन निचले स्तर पर कैसे भिन्न होता है?" गंदें शब्द बोलना। synchronized(OUTER_LOCK){ Thread.sleep(1000); }synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }OUTER_LOCKsleep
पेसियर

2
@ स्पेसर wait()आंतरिक सबसे लॉक की स्थिति से जुड़ा हुआ है जिसे इसे अपने कोड उदाहरण से कहा जाता है, wait()केवल जारी कर सकता है LOCKऔर नहीं OUTER_LOCK। वैसे भी जावा मॉनिटर को कैसे डिज़ाइन किया जाता है। एक निष्पक्ष तुलना होगी synchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }और synchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }। इस मामले में sleep()दोनों तालों wait()को जारी करेगा, LOCKलेकिन फिर भी पकड़OUTER_LOCK
danze

243

मुझे यह पोस्ट मददगार लगी। यह अंतर के बीच डालता है Thread.sleep(), Thread.yield()और Object.wait()मानव संदर्भ में। उद्धरण के लिए:

यह सब अंततः ओएस के अनुसूचक के लिए अपना रास्ता बनाता है, जो प्रक्रियाओं और थ्रेड्स के लिए समय-समय पर हाथ देता है।

sleep(n)कहते हैं, "मैं अपने समय के साथ कर रहा हूँ, और कृपया मुझे कम से कम n मिलीसेकंड के लिए एक और एक मत दो।" ओएस भी सोने के धागे को शेड्यूल करने का प्रयास नहीं करता है जब तक कि अनुरोधित समय बीत नहीं गया है।

yield()कहते हैं, "मैं अपने समय के साथ कर रहा हूँ, लेकिन मुझे अभी भी काम करना है।" OS थ्रेड को तुरंत एक और टाइमस्लाइज़ देने के लिए स्वतंत्र है, या कुछ अन्य थ्रेड देने के लिए या सीपीयू को उपज देने वाले धागे को बस देने की प्रक्रिया करें।

wait()कहते हैं, "मैं अपने समय के साथ किया जाता हूँ। जब तक कोई व्यक्ति सूचित () नहीं कहता तब तक मुझे दूसरा समय न दें। sleep()जब तक कोई फोन नहीं करता notify()(या कुछ अन्य वेकअप परिदृश्यों में से एक होता है) के साथ , ओएस आपके कार्य को शेड्यूल करने का प्रयास भी नहीं करेगा ।

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

आपको शायद ही कभी आवश्यकता होती है yield(), लेकिन अगर आपके पास तार्किक कार्य सीमाओं के साथ एक कम्प्यूट-भारी ऐप है, तो सिस्टम जवाबदेही में सुधार yield() हो सकता है (समय के संदर्भ में - संदर्भ स्विच, यहां तक ​​कि केवल ओएस और बैक पर, स्वतंत्र नहीं हैं)। माप और उन लक्ष्यों के खिलाफ परीक्षण करें जिनकी आप हमेशा की तरह देखभाल करते हैं।


यील्ड मूल रूप से प्लेटफ़ॉर्म-निर्भर है ... javamex.com/tutorials/threads/yield.shtml
पैसरियर

की व्याख्या sleep(n)स्पष्ट रूप से कह रही है कि वर्तमान में चल रहा धागा लॉक के मॉनिटर को स्वेच्छा से त्याग देता है, जो कि सच नहीं हैथ्रेड के जावाडॉक से उद्धरण : "धागा किसी भी मॉनिटर का स्वामित्व नहीं खोता है।"
क्लिंट ईस्टवुड

2
@ जोनाथन के उत्तर में मॉनिटर का कोई उल्लेख नहीं है, और ऐसा इसलिए है क्योंकि sleepकिसी अन्य जावा विधि कॉल की तुलना में मॉनिटर के बारे में कोई विशेष व्यवहार नहीं है, अर्थात यह किसी भी तरह से उन्हें इंटरैक्ट या संशोधित नहीं करता है। यदि आप मॉनिटर के बारे में कुछ कहेंगे तो आपको यह निर्दिष्ट करना चाहिए waitकि उपरोक्त बातों के अलावा, अस्थायी रूप से उस ऑब्जेक्ट पर लॉक को त्यागें, जिस पर उसे कॉल किया जाता है।
pqnet

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

@ समृद्ध, के wait(n)साथ तुलना करने के लिए उपयोग करें sleep(n)। नो-आर्ग का उपयोग करके तुलना करने में कोई समझदारी नहीं है।
पचेरियर

68

यहाँ बहुत सारे उत्तर हैं, लेकिन मैं किसी पर वर्णित अर्थ भेद नहीं पा सका।

यह धागे के बारे में ही नहीं है; दोनों तरीकों की आवश्यकता होती है क्योंकि वे बहुत भिन्न उपयोग-मामलों का समर्थन करते हैं।

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

wait(), इसके विपरीत, एक थ्रेड (या संदेश) सिंक्रनाइज़ेशन तंत्र है जो आपको एक थ्रेड को सूचित करने की अनुमति देता है जिसका आपके पास कोई संग्रहीत संदर्भ नहीं है (न ही देखभाल)। आप इसे एक प्रकाशन-सदस्यता पैटर्न ( wait== सदस्यता और notify()== प्रकाशन) के रूप में सोच सकते हैं । मूल रूप से सूचित () का उपयोग कर आप एक संदेश भेज रहे हैं (जो कि बिल्कुल भी प्राप्त नहीं किया जा सकता है और आमतौर पर आप परवाह नहीं करते हैं)।

योग करने के लिए, आप सामान्य रूप sleep()से समय-सिंक्रनाइज़ेशन के लिए और wait()बहु-थ्रेड-सिंक्रनाइज़ेशन के लिए उपयोग करते हैं।

उन्हें अंतर्निहित ओएस में एक ही तरीके से लागू किया जा सकता है, या बिल्कुल नहीं (जैसा कि जावा के पिछले संस्करणों में कोई वास्तविक मल्टीथ्रेडिंग नहीं था; शायद कुछ छोटे वीएम भी ऐसा नहीं करते हैं)। जावा को VM पर न भूलें, इसलिए आपका कोड VM / OS / HW के अनुसार कुछ अलग में बदल जाएगा।


54

यहाँ, मैं के बीच कुछ महत्वपूर्ण अंतर को सूचीबद्ध किया है wait()और sleep()तरीकों।
पुनश्च: इसके अलावा पुस्तकालय कोड (आंतरिक काम करने के लिए लिंक पर क्लिक करें, बेहतर समझ के लिए बस थोड़ा सा आसपास खेलें)।

रुको()

  1. wait() विधि ताला जारी करता है।
  2. wait()Objectकक्षा की विधि है ।
  3. wait() गैर-स्थैतिक विधि है - public final void wait() throws InterruptedException { //...}
  4. wait()notify()या notifyAll()तरीकों से सूचित किया जाना चाहिए ।
  5. wait() झूठी अलार्म से निपटने के लिए एक लूप से विधि की आवश्यकता होती है।

  6. wait() विधि को समकालिक संदर्भ (अर्थात सिंक्रोनाइज़्ड विधि या ब्लॉक) से पुकारा जाना चाहिए, अन्यथा वह फेंक देगा IllegalMonitorStateException

नींद ()

  1. sleep() विधि लॉक जारी नहीं करता है।
  2. sleep()java.lang.Threadकक्षा की विधि है ।
  3. sleep() स्थैतिक विधि है - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. निर्दिष्ट समय के बाद, sleep()पूरा हो गया है।
  5. sleep()लूप से कॉल न करना बेहतर है (यानी नीचे कोड देखें )।
  6. sleep()कहीं से भी बुलाया जा सकता है। कोई विशेष आवश्यकता नहीं है।

Ref: प्रतीक्षा और नींद के बीच अंतर

प्रतीक्षा और नींद विधि को कॉल करने के लिए कोड स्निपेट

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

विभिन्न धागा राज्यों में धागा संक्रमण


क्या यह सही है कि सोते हुए धागे को सूचित करने के लिए कॉल करके जगाया जा सकता है ()? यहाँ कुछ अन्य पोस्टों से लगता है कि एक सोने के धागे को जगाया नहीं जा सकता है लेकिन उसे बाधित किया जाता है।
बेरीम्बोलो

हां, Thread.sleep()दूसरे थ्रेड्स के लिए प्रोसेसर समय उपलब्ध कराने के लिए उपयोग किया जाता है। नींद की अवधि को इंटरप्ट (जेवीएम द्वारा) समाप्त किया जा सकता है। यह पढ़ें stackoverflow.com/questions/4264355/…
roottraveller

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

@berimbolo notify()या notifyAll()कर रहे हैं Objectवर्ग तरीकों। इसलिए वे उपलब्ध हैं सभी वर्ग (यानी यहाँ Threadभी वर्ग के साथ ) का पालन करेंगे। कोड को देखने के grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/...
roottraveller

2
ठीक है, मुझे थ्रेड शेड्यूलिंग पर और अधिक पढ़ने की आवश्यकता है क्योंकि मुझे सूचित करने के उदाहरण नहीं मिल सकते हैं () या नोटिफिकेशन () सोते हुए थ्रेड्स को केवल बाधित करना () ऐसा करना। सभी उदाहरण कुछ मॉनिटर ऑब्जेक्ट पर प्रतीक्षा कर रहे थ्रेड्स को सूचित करें () और नोटिफिकेशन () से संबंधित हैं।
बेरीम्बोलो

29

प्रतीक्षा और नींद पर काम करने के बाद कुछ अंतर महत्वपूर्ण नोट हैं, जो पहले प्रतीक्षा () और नींद () का उपयोग करके नमूना पर एक नज़र डालते हैं:

उदाहरण 1 : प्रतीक्षा () और नींद () का उपयोग करना :

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

स्पष्टता दें कुछ प्रमुख नोट:

  1. पर कॉल करें :
    • प्रतीक्षा करें (): हैंडऑबजेक्ट ऑब्जेक्ट को रखने वाले वर्तमान थ्रेड पर कॉल करें
    • नींद (): थ्रेड एग्जीक्यूट टास्क पर कॉल बीयर मिलती है (वर्तमान में चल रहे थ्रेड पर वर्ग विधि इतनी प्रभावित होती है)
  2. सिंक्रनाइज़ :
    • प्रतीक्षा करें (): जब सिंक्रनाइज़ किए गए मल्टी थ्रेड एक्सेस एक ही ऑब्जेक्ट (हैंडऑबजेक्ट) (जब एक से अधिक थ्रेड के बीच संचार की आवश्यकता हो (थ्रेड एग्जीक्यूट कोडिंग, थ्रेड एग्जीक्यूट बियर मिल जाए) एक ही ऑब्जेक्ट पर एक्सेस करें हैंडऑबजेक्ट)
    • नींद (): जब निष्पादित करने के लिए प्रतीक्षा करने की स्थिति (उपलब्ध बीयर की प्रतीक्षा)
  3. ताला पकड़ो :
    • प्रतीक्षा (): अन्य ऑब्जेक्ट के लिए लॉक को निष्पादित करने का मौका है (हैंडऑब्जेक्ट मुफ्त है, आप अन्य काम कर सकते हैं)
    • नींद (): कम से कम टी बार (या बीच तक) के लिए लॉक रखें (मेरा काम अभी भी खत्म नहीं हुआ है, मैं लॉक को जारी रख रहा हूं और जारी रखने के लिए कुछ शर्त का इंतजार कर रहा हूं)
  4. जागने की स्थिति :
    • प्रतीक्षा (): जब तक कॉल नोटिफ़िकेशन (), नोटिफिकेशन () ऑब्जेक्ट से
    • नींद (): कम से कम समय समाप्त होने तक या कॉल को बाधित करना
  5. और अंतिम बिंदु का उपयोग तब किया जाता है जब एस्टानी संकेत देते हैं:

आप बहु-थ्रेड-सिंक्रनाइज़ेशन के लिए सामान्य रूप से समय-सिंक्रनाइज़ेशन और प्रतीक्षा () के लिए नींद का उपयोग करते हैं।

कृपया मुझे सुधारें अगर मैं गलत हूं।


25

प्रतीक्षा () और नींद () के बीच अंतर

  • मौलिक अंतर यह है कि wait()से है Objectऔर sleep()एक स्थिर विधि है Thread

  • प्रमुख अंतर यह है कि प्रतीक्षा करते समय कोई भी लॉक जारी नहीं करता है, wait()जबकि लॉक को sleep()रिलीज़ करता है।

  • wait()अंतर-थ्योरी संचार के लिए उपयोग किया जाता है, जबकि sleep()आम तौर पर निष्पादन पर रोक लगाने के लिए उपयोग किया जाता है।

  • wait()अंदर से बुलाया जाना चाहिए या हमें एक मिल जाएगा IllegalMonitorStateException, जबकि sleep()कहीं भी बुलाया जा सकता है।

  • फिर से एक धागा शुरू करने के लिए wait(), आपको कॉल करना होगा notify()या notifyAll()। के रूप sleep(),में धागे के लिए एक निर्दिष्ट समय अंतराल के बाद शुरू हो जाता है।

समानताएँ

  • दोनों वर्तमान थ्रेड को रन करने योग्य स्थिति में नहीं जाते हैं ।
  • दोनों ही देशी तरीके हैं।

18

यह एक बहुत ही सरल प्रश्न है, क्योंकि इन दोनों विधियों का बिल्कुल अलग उपयोग है।

मुख्य अंतर ताला बंद करने या मॉनिटर करने के लिए प्रतीक्षा करना है जबकि सोते समय कोई ताला या मॉनिटर जारी नहीं करता है। प्रतीक्षा का उपयोग इंटर-थ्रेड संचार के लिए किया जाता है जबकि नींद का उपयोग निष्पादन पर रोक लगाने के लिए किया जाता है।

यह सिर्फ एक स्पष्ट और बुनियादी स्पष्टीकरण था, यदि आप इससे अधिक चाहते हैं तो पढ़ना जारी रखें।

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

लेकिन इसके मामले में sleep()एक विधि है जिसका उपयोग प्रक्रिया को कुछ सेकंड या आपके द्वारा वांछित समय के लिए किया जाता है। क्योंकि आपको उस धागे को वापस पाने के लिए किसी विधि notify()या notifyAll()विधि को भड़काने की आवश्यकता नहीं है । या आपको उस धागे को वापस बुलाने के लिए किसी अन्य धागे की आवश्यकता नहीं है। जैसे यदि आप चाहते हैं कि कुछ सेकंड के बाद कुछ होना चाहिए जैसे कि उपयोगकर्ता की बारी के बाद आप चाहते हैं कि उपयोगकर्ता तब तक प्रतीक्षा करे जब तक कि कंप्यूटर नहीं चलता है तब आप sleep()विधि का उल्लेख कर सकते हैं ।

और एक और महत्वपूर्ण अंतर है जो साक्षात्कार में अक्सर पूछा जाता है: sleep()के अंतर्गत आता है Threadवर्ग और wait()के अंतर्गत आता है Objectवर्ग।

ये सभी sleep()और के बीच के अंतर हैं wait()

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

उम्मीद है इससे आपको मदद मिलेगी।


16

स्रोत: http://www.jguru.com/faq/view.jsp?EID=47127

Thread.sleep()वर्तमान थ्रेड को कुछ समय के लिए "Not Runnable" स्थिति में भेजता है । थ्रेड मॉनिटर को रखता है जो इसे एक्वायर्ड करता है - अर्थात यदि थ्रेड वर्तमान में एक सिंक्रोनाइज़्ड ब्लॉक या विधि में है तो कोई भी थ्रेड इस ब्लॉक या मेथड में प्रवेश नहीं कर सकता है। अगर कोई दूसरा धागा कहता है तो t.interrupt()यह सोने वाले धागे को जगाएगा।

ध्यान दें कि नींद एक स्थिर विधि है, जिसका अर्थ है कि यह हमेशा वर्तमान धागे (नींद की विधि को निष्पादित करने वाली) को प्रभावित करता है। एक सामान्य गलती यह है कि t.sleep()जहां टी एक अलग धागा है; फिर भी, यह वर्तमान धागा है जो सोएगा, टी धागा नहीं।

t.suspend()पदावनत किया गया है। इसका उपयोग करना वर्तमान धागे के अलावा एक धागे को रोकना संभव है। एक निलंबित धागा अपने सभी मॉनिटर रखता है और चूंकि यह राज्य बाधित नहीं है इसलिए यह गतिरोध प्रवण है।

object.wait()वर्तमान थ्रेड को "Not Runnable" स्थिति में भेजता है , जैसे sleep(), लेकिन एक मोड़ के साथ। प्रतीक्षा को एक वस्तु कहा जाता है, एक धागा नहीं; हम इस ऑब्जेक्ट को "लॉक ऑब्जेक्ट" कहते हैं। lock.wait()कॉल करने से पहले , वर्तमान थ्रेड को लॉक ऑब्जेक्ट पर सिंक्रनाइज़ करना चाहिए; wait() फिर इस लॉक को रिलीज़ करता है, और लॉक से जुड़े "प्रतीक्षा सूची" में थ्रेड जोड़ता है। बाद में, एक और धागा एक ही लॉक ऑब्जेक्ट पर कॉल और सिंक्रनाइज़ कर सकता है lock.notify()। यह मूल, प्रतीक्षा धागे को जगाता है। मूल रूप से, wait()/ notify()जैसा है sleep()/ interrupt(), केवल सक्रिय थ्रेड को स्लीपिंग थ्रेड के लिए प्रत्यक्ष सूचक की आवश्यकता नहीं है, लेकिन केवल साझा लॉक ऑब्जेक्ट के लिए।


14

प्रतीक्षा और नींद दो अलग-अलग चीजें हैं:

  • में sleep()धागा निर्दिष्ट अवधि के लिए काम करना बंद।
  • में wait()धागा काम कर जब तक वस्तु से किया जा रहा इंतजार कर रहे थे-ऑन सूचित किया जाता है, आम तौर पर अन्य धागे से बंद हो जाता है।

लेकिन आप एक नींद थ्रेड को बाधित कर सकते हैं। में उस मामले प्रतीक्षा () अनावश्यक वास्तव में है यह भी CPU चक्र बरबाद करती है :-(
गीक

9
रुको सीपीयू साइकिल बर्बाद नहीं करता है।
पीटर attibraný

1
@Peter - मुझे लगता है कि यह करता है। यह सीपीयू चक्रों के अपने हिस्से के लिए इंतजार () करता है और फिर ओएस सीपीयू चक्रों को अन्य थ्रेड्स को देता है। मुझे लगता है कि यह ओएस पर निर्भर हो सकता है, मुझे यकीन नहीं है।
गीक

3
यह प्रतीक्षा के बहुत खराब कार्यान्वयन होगा () अगर यह सीपीयू चक्र बर्बाद कर दिया। प्रतीक्षा / सूचना का उपयोग अंतःसंस्थान संचार के लिए काफी किया जाता है।
पीटर attibraný

2
@ दो निर्माण अलग उद्देश्य के लिए किए गए हैं। यदि आप चाहते हैं कि आपके द्वारा उपयोग किए जाने वाले निश्चित समय के लिए कोई थ्रेड बंद हो जाए sleep, यदि आप चाहते हैं कि जब तक आपके द्वारा उपयोग किए waitजाने वाले अन्य से कुछ इनपुट न आए, तब तक इसे रोकें notifyinterruptएक सूत्र को इंगित करने के तरीके के रूप में अभिप्रेत है कि यह जो कर रहा है उसे समाप्त करना बंद कर देना चाहिए। यह द्वारा नियंत्रित किया जाता है sleep, waitलेकिन I / O फ़ंक्शन को भी अवरुद्ध करता है (और आप विधि को कॉल करके समान व्यवहार के साथ कार्य कार्यान्वित कर सकते हैं Thread.interrupted())। प्रदर्शन के लिए, फ़ंक्शन आमतौर पर उनके द्वारा डिज़ाइन किए गए लक्ष्य के लिए अनुकूलित होते हैं।
pqnet

11

sleepकी एक विधि है Thread, waitकी एक विधि है Object, इसलिए wait/notifyजावा ( मॉनिटर का उपयोग करके ) में साझा डेटा को सिंक्रनाइज़ करने की एक तकनीक है , लेकिन sleepखुद को रोकने के लिए धागे की एक सरल विधि है।


8

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

बड़ा अंतर यह है कि प्रतीक्षा () ताला या मॉनिटर विज्ञप्ति जबकि नींद () प्रतीक्षा करते हुए किसी भी ताला या मॉनिटर नहीं रिलीज करता है। प्रतीक्षा का उपयोग इंटर-थ्रेड संचार के लिए किया जाता है, जबकि नींद का उपयोग निष्पादन पर रोक लगाने के लिए किया जाता है, आमतौर पर।

थ्रेड.स्लीप () वर्तमान थ्रेड को "नॉट रननेबल" स्थिति में कुछ समय के लिए भेजता है। धागा अपने द्वारा अधिग्रहित किए गए मॉनिटर को रखता है - अर्थात यदि धागा वर्तमान में सिंक्रनाइज़ ब्लॉक या विधि में है, तो कोई अन्य धागा इस ब्लॉक या विधि में प्रवेश नहीं कर सकता है। यदि कोई अन्य थ्रेड t.interrupt () कहता है तो यह स्लीपिंग थ्रेड को जगाएगा। ध्यान दें कि नींद एक स्थिर विधि है, जिसका अर्थ है कि यह हमेशा वर्तमान धागे (नींद की विधि को निष्पादित करने वाली) को प्रभावित करता है। एक सामान्य गलती t.sleep () को कॉल करना है जहां t एक अलग धागा है; फिर भी, यह वर्तमान धागा है जो सोएगा, टी धागा नहीं।

object.wait () वर्तमान थ्रेड को "Not Runnable" स्थिति में भेजता है, जैसे नींद (), लेकिन एक मोड़ के साथ। प्रतीक्षा को एक वस्तु कहा जाता है, एक धागा नहीं; हम इस ऑब्जेक्ट को "लॉक ऑब्जेक्ट" कहते हैं। लॉक होने से पहले। () कहा जाता है, वर्तमान थ्रेड को लॉक ऑब्जेक्ट पर सिंक्रनाइज़ करना चाहिए; प्रतीक्षा () तब इस लॉक को रिलीज़ करता है, और लॉक से जुड़े "प्रतीक्षा सूची" में धागा जोड़ता है। बाद में, एक और धागा एक ही लॉक ऑब्जेक्ट पर कॉल कर सकते हैं और लॉक कर सकते हैं। नोट () करें। यह मूल, प्रतीक्षा धागे को जगाता है। मूल रूप से, प्रतीक्षा () / सूचित () नींद की तरह है () / व्यवधान (), केवल सक्रिय थ्रेड को स्लीपिंग थ्रेड के लिए प्रत्यक्ष सूचक की आवश्यकता नहीं है, लेकिन केवल साझा लॉक ऑब्जेक्ट के लिए।

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}

उपरोक्त सभी बिंदुओं को वर्गीकृत करें:

Call on:

  • प्रतीक्षा (): किसी वस्तु पर कॉल करें; वर्तमान थ्रेड को लॉक ऑब्जेक्ट पर सिंक्रनाइज़ करना होगा।
  • नींद (): एक थ्रेड पर कॉल करें; हमेशा वर्तमान में थ्रेड को निष्पादित करना।

Synchronized:

  • प्रतीक्षा (): जब सिंक्रनाइज़ किए गए कई धागे एक ही ऑब्जेक्ट को एक-एक करके एक्सेस करते हैं।
  • नींद (): जब सिंक्रनाइज़ किए गए कई धागे नींद के धागे की नींद की प्रतीक्षा करते हैं।

Hold lock:

  • प्रतीक्षा (): निष्पादित करने का मौका देने के लिए अन्य वस्तुओं के लिए ताला जारी करें।
  • सो जाओ (): कम से कम टी बार लॉकआउट रखें यदि टाइमआउट निर्दिष्ट किया गया है या किसी ने बाधित किया है।

Wake-up condition:

  • प्रतीक्षा (): जब तक कॉल नोटिफ़िकेशन (), नोटिफिकेशन () ऑब्जेक्ट से
  • नींद (): कम से कम समय समाप्त होने तक या कॉल बाधित ()।

Usage:

  • नींद (): समय-तुल्यकालन के लिए और;
  • प्रतीक्षा (): बहु-सूत्र-सिंक्रनाइज़ेशन के लिए।

रेफरी: अंतर sleepऔरwait


6

सरल शब्दों में, प्रतीक्षा तब तक प्रतीक्षा की जाती है जब तक कि कुछ अन्य सूत्र आपको आमंत्रित नहीं करते हैं, जबकि नींद कुछ निर्दिष्ट अवधि के लिए "अगले कथन को निष्पादित नहीं करती है"।

इसके अलावा नींद थ्रेड क्लास में स्थिर विधि है और यह थ्रेड पर काम करती है, जबकि प्रतीक्षा () ऑब्जेक्ट क्लास में होती है और ऑब्जेक्ट पर कॉल की जाती है।

एक अन्य बिंदु, जब आप किसी वस्तु पर प्रतीक्षा कहते हैं, तो इसमें शामिल धागा वस्तु को सिंक्रनाइज़ करता है और फिर प्रतीक्षा करता है। :)


1
आपको दोनों की आवश्यकता क्यों है? नींद () पर्याप्त क्यों नहीं है?
गीक

2
नोटिफिकेशन का उपयोग थ्रेड्स के बीच संचार के लिए किया जाता है। प्रतीक्षा को कॉल करने के लिए, आपको कुछ ऑब्जेक्ट की आवश्यकता होती है, उस पर सिंक्रनाइज़ करें, और फिर उस पर प्रतीक्षा कॉल करें। अधिसूचित होने के लिए, आपको एक ही ऑब्जेक्ट पर सिंक्रनाइज़ करने के लिए अन्य थ्रेड की आवश्यकता है , और सूचित करें।
पीटर attibraný

6

waitऔर sleepतरीके बहुत अलग हैं:

  • sleep "जागने" का कोई तरीका नहीं है,
  • जबकि waitप्रतीक्षा अवधि के दौरान "जागने" का एक तरीका है, एक और धागा कॉलिंग द्वारा notifyया notifyAll

इसके बारे में सोचने के लिए आओ, नाम उस संबंध में भ्रमित कर रहे हैं; हालाँकि sleep, एक मानक नाम है और Win API में या waitजैसा है।WaitForSingleObjectWaitForMultipleObjects


3
लेकिन हम एक नींद को बाधित कर सकते हैं हम नहीं कर सकते? तो उस नींद / रुकावट बनाम प्रतीक्षा / सूचना के साथ क्या अंतर है?
पचेरियर

2
आप एक नींद वाले व्यक्ति को बाधित कर सकते हैं, लेकिन आप केवल प्रतीक्षा करने वाले व्यक्ति को सूचित कर सकते हैं। धागे समान हैं।
ऋषि

5

इस पोस्ट से: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

प्रतीक्षा () विधि।

1) थ्रेड जिसे कॉल प्रतीक्षा () विधि लॉक रखती है उसे जारी करता है।

2) थ्रेड एक ही लॉक पर अन्य थ्रेड्स को सूचित () या InformAll () विधियों को कॉल करने के बाद लॉक को पुनः प्राप्त करता है।

3) प्रतीक्षा () विधि को सिंक्रनाइज़ ब्लॉक के भीतर बुलाया जाना चाहिए।

4) प्रतीक्षा () विधि को हमेशा वस्तुओं पर कहा जाता है।

5) वेटिंग थ्रेड्स को अन्य थ्रेड्स द्वारा सूचित () या नोटिफिकेशन () तरीकों से कॉल करके जगाया जा सकता है।

6) प्रतीक्षा () विधि को कॉल करने के लिए, थ्रेड में ऑब्जेक्ट लॉक होना चाहिए।

नींद () विधि

1) थ्रेड जिसे स्लीप कहते हैं () विधि उस लॉक को रिलीज़ नहीं करती है जो इसे धारण करता है।

2) नींद () विधि को सिंक्रनाइज़ ब्लॉक के भीतर या बाहर बुलाया जा सकता है।

3) नींद () विधि को हमेशा थ्रेड्स पर कहा जाता है।

४) सोते हुए धागों को अन्य धागों से नहीं जगाया जा सकता है। यदि ऐसा किया जाता है, तो थ्रेड InterruptedException को फेंक देगा।

5) स्लीप () विधि को कॉल करने के लिए, थ्रेड को ऑब्जेक्ट लॉक नहीं होना चाहिए।


4
  1. wait()Objectकक्षा की एक विधि है । कक्षा
    sleep()की एक विधि है Thread

  2. sleep()धागे को sleepएक्स मिलीसेकंड के लिए राज्य में जाने की अनुमति देता है ।
    जब एक धागा नींद की स्थिति में चला जाता है it doesn’t release the lock

  3. wait()धागे को ताला जारी करने की अनुमति देता है और goes to suspended state
    यह धागा सक्रिय है जब एक हो जाएगा notify()या notifAll()विधि एक ही वस्तु के लिए कहा जाता है।


4

नींद / रुकावट और प्रतीक्षा / सूचना के बीच एक संभावित बड़ा अंतर है

  • कॉलिंग के interrupt()दौरान sleep()हमेशा एक अपवाद (जैसे InterruptedException ) फेंकता है , जबकि
  • के notify()दौरान फोन wait()नहीं करता है।

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


+1, वास्तव में एक मान्य बिंदु, हालांकि कार्यान्वयन के आंतरिक बिंदुओं पर बहस करना प्रदर्शन विश्लेषण के लिए अधिक प्रासंगिक हो सकता है ...
पचेरियर

दूसरे शब्दों में अपवाद बनाने का ओवरहेड सिस्टम बनाम एक के कार्यान्वयन के ओवरहेड की तुलना में काफी छोटा हो सकता है।
पचेरियर

3

आप सही हैं - स्लीप () उस थ्रेड को "स्लीप" करने का कारण बनता है और सीपीयू बंद हो जाएगा और अन्य थ्रेड्स (अन्यथा संदर्भ स्विचिंग के रूप में जाना जाता है) को संसाधित करता है। मेरा मानना ​​है कि प्रतीक्षा करें सीपीयू को वर्तमान थ्रेड को संसाधित करता रहता है।

हमारे पास दोनों हैं क्योंकि यद्यपि यह समझ में आता है कि आप इसका उपयोग नहीं करते हुए अन्य लोगों को सीपीयू का उपयोग करने दें, वास्तव में संदर्भ स्विचिंग के लिए एक ओवरहेड है - यह निर्भर करता है कि नींद कितनी देर तक है, यह सीपीयू चक्रों में अधिक महंगा हो सकता है थ्रेड्स को स्विच करने की तुलना में यह है कि आपके थ्रेड को कुछ एमएस के लिए कुछ भी नहीं करना है।

यह भी ध्यान दें कि नींद एक संदर्भ स्विच को मजबूर करती है।

इसके अलावा - सामान्य तौर पर संदर्भ स्विचिंग को नियंत्रित करना संभव नहीं है - प्रतीक्षा के दौरान ओएस अन्य थ्रेड्स को संसाधित करने के लिए ओएस का चयन कर सकता है (और लंबे समय तक इंतजार करेगा)।


4
प्रतीक्षा () सीपीयू को वर्तमान थ्रेड को संसाधित नहीं करता है। यह नींद की तरह है कि यह एक संदर्भ स्विच का कारण बनता है: javamex.com/tutorials/threads/context_switch.shtml । मैं स्टैकओवरफ्लो के चारों ओर आधे साल से पूछ रहा हूं और ऐसा लगता है कि किसी को भी नहीं पता है कि प्रतीक्षा / अधिसूचित बनाम नींद / बीच का अंतर क्या है।
पचेरियर

हालाँकि, नींद वर्तमान धागे के प्रसंस्करण में सीपीयू नहीं रखती है, मुझे लगता है, यह वैसे भी सीपीयू के लिए थोड़ा बोझ है, क्योंकि सीपीयू को नींद को खत्म करने के क्षण को ट्रैक करने की आवश्यकता होती है। यह प्रतीक्षा में "सूचित" जैसे बाहरी ट्रिगर नहीं है। नहीं?
व्लादिमीर नाबोकोव

@ व्लादिमीर नाबोकोव, बाहरी ट्रिगर है interrupt। समाप्त होने का समय है nमें wait(n)। Years अब 8 साल हो गए हैं और अभी भी इसका जवाब किसी के पास नहीं है!
पचेरियर

3

तरीकों का उपयोग विभिन्न चीजों के लिए किया जाता है।

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.sleep (n) बाधित हो सकता है, लेकिन Object.wait () को सूचित किया जाना चाहिए। प्रतीक्षा करने के लिए अधिकतम समय निर्दिष्ट करना संभव है: Object.wait(5000)इसलिए इसका उपयोग waitकरना, गिराना संभव होगा , sleepलेकिन फिर आपको ताले से परेशान करना होगा।

सोते / प्रतीक्षा करते समय न तो तरीकों में से एक सीपीयू का उपयोग करता है।

विधियों को मूल कोड का उपयोग करके लागू किया जाता है, समान निर्माणों का उपयोग करके लेकिन उसी तरह से नहीं।

स्वयं की तलाश करें: क्या मूल तरीकों का स्रोत कोड उपलब्ध है? फ़ाइल /src/share/vm/prims/jvm.cppप्रारंभिक बिंदु है ...


थ्रेड.स्लीप टाइमिंग को अनिश्चित काल के लिए भी सेट किया जा सकता है। Object.wait समय निश्चित करने के लिए भी सेट किया जा सकता है। यह उत्तर स्पष्ट नहीं करता है कि हमें 2 हथौड़ों की आवश्यकता क्यों है जो समान कार्य करते हैं।
पचेरियर

Thread.sleep(big_num) बाधित होना चाहिए। अधिसूचित किया Object.wait(small_num) जा सकता है।
पचेरियर

3

यहाँ प्रतीक्षा () वेटिंग स्टेट में होगी जब तक कि यह किसी अन्य थ्रेड द्वारा सूचित नहीं किया जाता है, लेकिन जहां नींद () कुछ समय के लिए होगी..इसके बाद यह स्वचालित रूप से रेडी स्थिति में स्थानांतरित हो जाएगी ...


3

रुको () और नींद () अंतर?

Thread.sleep () एक बार जब इसका काम पूरा हो जाता है, उसके बाद ही इसका लॉक सभी के लिए जारी किया जाता है। जब तक इसके लॉक को किसी को जारी नहीं किया जाता है।

  Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

Object.wait () जब इसकी वेटिंग स्टेज पर जाती है, तो यह कुंजी और इसके कुछ सेकेंड के आधार पर वेटिंग जारी करेगा।

उदाहरण के लिए:

आप अपने दाहिने हाथ में कॉफी ले रहे हैं, आप उसी हाथ से किसी अन्य व्यक्ति को ले जा सकते हैं, जब आपका पुट नीचे होगा तब केवल एक अन्य वस्तु यहां ले जाएं। भी। यह नींद है () आप सोते समय आप कोई काम नहीं करते थे, आप केवल सो रहे हैं .. यहाँ भी।

रुको()। जब आपको नीचे रखा जाता है और प्रतीक्षा करते समय एक और मतलब निकाला जाता है, तो वह प्रतीक्षा है

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


3

waitताला जारी sleepकरता है और नहीं करता है। प्रतीक्षा की स्थिति में एक धागा जल्द से जल्द जागने के योग्य है notifyया notifyAllकहा जाता है। लेकिन sleepधागे के मामले में ताला लगा रहता है और सोने का समय पूरा होने के बाद ही यह पात्र होगा।


तो अगर धागा 10 सेकंड के लिए सो रहा है और एक बाधित अपवाद होता है ????
गीक

@ गीक एन InterruptedExceptionको फेंक दिया जाता है, जैसा कि जावदोक में कहा गया है।
user207421

@ ईजेपी: क्या आप वही ईजेपी हैं जो sun.java.com मंचों पर थे? कम से कम आपका स्कोर कम ही पता चलता है :-)
Geek

2

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

wait() विधि वर्तमान थ्रेड को निर्दिष्ट समय तक या सूचित करने तक ब्लॉक स्थिति में जाने का कारण बनती है, लेकिन इस स्थिति में थ्रेड ऑब्जेक्ट का लॉक रिलीज़ करता है (जिसका अर्थ है कि अन्य थ्रेड्स कॉलिंग ऑब्जेक्ट के किसी भी सिंक्रनाइज़ किए गए तरीकों को निष्पादित कर सकते हैं।


2

मेरी राय में, दोनों तंत्रों के बीच मुख्य अंतर यह है कि थ्रेड को संभालने का सबसे बुनियादी तरीका नींद / रुकावट है, जबकि प्रतीक्षा / सूचना थ्रेड इंटर-कम्युनिकेशन को आसान बनाने के लिए एक अमूर्त उद्देश्य है। इसका मतलब है कि नींद / रुकावट कुछ भी कर सकती है, लेकिन यह विशिष्ट कार्य करना कठिन है।

प्रतीक्षा / सूचना अधिक उपयुक्त क्यों है? यहाँ कुछ व्यक्तिगत विचार दिए गए हैं:

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

  2. यह सिंक्रोनाइज़ेशन को लागू करता है। क्योंकि यह प्रोग्रामर को सिंक्रनाइज़ ब्लॉक में प्रतीक्षा / सूचित करने के लिए कॉल को लपेटता है।

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

वास्तविक जीवन से एक उदाहरण जो यह समझाने के लिए अच्छा है कि एक क्लासिक रेस्तरां और विधि है कि कार्मिक उनके बीच संवाद करने के लिए उपयोग करते हैं: वेटर ग्राहक के अनुरोधों को एक केंद्रीय स्थान (एक कॉर्क बोर्ड, एक तालिका, आदि) में छोड़ देते हैं। घंटी बजाओ, और रसोई से कामगार ऐसे अनुरोध लेने आते हैं। एक बार जब कोई भी कोर्स तैयार हो जाता है, तो रसोई के कर्मचारी फिर से घंटी बजाते हैं ताकि वेटर जागरूक हों और उन्हें ग्राहकों के पास ले जाएं।


2

नींद के बारे में उदाहरण ताला जारी नहीं करता है और प्रतीक्षा करता है

यहाँ दो वर्ग हैं:

  1. मुख्य : मुख्य विधि और दो धागे शामिल हैं।
  2. सिंगलटन : यह एकल वर्ग है जिसमें दो स्थिर विधियाँ प्राप्त होती हैं () और getInstance (बूलियन isWait)।

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

तथा

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

अब इस उदाहरण को रन करें जो आपको आउटपुट के नीचे मिलेगा:

_instance :null
Both singleton are same

यहां थ्रेडा और थ्रेडबी द्वारा निर्मित सिंगलटन इंस्टेंस समान हैं। इसका अर्थ है कि थ्रेडबी बाहर प्रतीक्षा कर रहा है जब तक थ्रेडा रिलीज़ नहीं होता है यह लॉक है।

अब Thread.sleep (500) टिप्पणी करके Singleton.java को बदलें; सिंग्लटन.क्लास.वाइट (500) मेथड एंड अनकम्प्लीमेंटिंग; । यहां सिंगलटन के कारण ।class.wait (500); विधि थ्रेडा सभी अधिग्रहीत ताले को छोड़ देगा और "नॉन रननेबल" स्थिति में चला जाएगा, थ्रेडबी को सिंक्रनाइज़ ब्लॉक में प्रवेश करने के लिए परिवर्तन मिलेगा।

अब फिर से चलाएं:

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

यहां थ्रेडा और थ्रेडबी द्वारा निर्मित सिंग्लटन इंस्टेंस समान नहीं हैं क्योंकि थ्रेडबी को सिंक्रोनाइज़्ड ब्लॉक में प्रवेश करने के लिए बदलाव मिला है और 500 मिलीसेकंड थ्रेडा के शुरू होने के बाद यह अंतिम स्थिति में है और एक और सिंगलटन ऑब्जेक्ट बनाया है।


2

सिंक्रोनाइज़्ड ब्लॉक से कॉल किया जाना चाहिए: wait() मेथड को हमेशा सिंक्रोनाइज़्ड ब्लॉक से पुकारा जाता है। wait()विधि को ऑब्जेक्ट मॉनिटर से पहले ऑब्जेक्ट को लॉक करने की आवश्यकता होती है, जिस पर इसे कहा जाता है। लेकिन sleep()विधि को बाहर से सिंक्रनाइज़ ब्लॉक से कहा जा सकता है अर्थात sleep()विधि को किसी ऑब्जेक्ट मॉनिटर की आवश्यकता नहीं है।

IllegalMonitorStateException: यदि रनटाइम पर wait()ऑब्जेक्ट लॉक प्राप्त करने के बिना विधि को कॉल किया जाता IllegalMonitorStateExceptionहै, लेकिन sleep()विधि कभी भी ऐसे अपवाद को नहीं फेंकता है।

किस वर्ग के wait() अंतर्गत आता है : विधि java.lang.Objectवर्ग की है लेकिन sleep()विधि java.lang.Threadवर्ग की है।

ऑब्जेक्ट या थ्रेड पर कॉल की गई: wait() विधि को ऑब्जेक्ट्स पर कहा जाता है, लेकिन sleep()थ्रेड्स ऑब्जेक्ट्स को विधि कहा जाता है।

थ्रेड राज्य: जब wait()विधि वस्तु पर कहा जाता है, थ्रेड कि holded वस्तु की निगरानी के राज्य इंतजार कर के चलने से चला जाता है और केवल जब runnable राज्य पर लौट सकते हैं notify()या notifyAll()विधि उस ऑब्जेक्ट पर कहा जाता है। और बाद में थ्रेड शेड्यूलर शेड्यूल होता है जो थ्रेडेबल से रनिंग स्टेट तक जाता है। जब sleep()इसे थ्रेड पर बुलाया जाता है तो यह रनिंग वेटिंग स्थिति में चला जाता है और स्लीप टाइम के उठने पर रन करने योग्य स्थिति में वापस आ सकता है।

जब सिंक्रोनाइज़्ड ब्लॉक से कॉल किया जाता है: जब wait()मेथड को थ्रेड कहते हैं तो ऑब्जेक्ट लॉक हो जाता है। लेकिन sleep()विधि जब सिंक्रोनाइज़्ड ब्लॉक या मेथड थ्रेड से कॉल की जाती है तो ऑब्जेक्ट लॉक नहीं होता है।

अधिक संदर्भ के लिए


शायद उस से एक बेहतर संदर्भ URL।
ड्रू

2

प्रतीक्षा पर oracle के प्रलेखन पृष्ठ से Object: की विधि :

public final void wait()
  1. वर्तमान थ्रेड को तब तक प्रतीक्षा करने का कारण बनता है जब तक कि कोई अन्य थ्रेड इस ऑब्जेक्ट के लिए notify()विधि या notifyAll()विधि को लागू नहीं करता है। दूसरे शब्दों में, यह विधि बिल्कुल वैसा ही व्यवहार करती है जैसे कि यह केवल कॉल करता है wait(0)
  2. वर्तमान थ्रेड को इस ऑब्जेक्ट का मॉनीटर होना चाहिए। थ्रेड इस मॉनीटर के स्वामित्व को रिलीज़ करता है और तब तक प्रतीक्षा करता है जब तक कि कोई अन्य थ्रेड इस ऑब्जेक्ट के मॉनीटर पर जागने वाले थ्रेड्स को सूचित नहीं करता
  3. इंटरप्ट और स्प्यूरियस वेकअप संभव हैं
  4. इस विधि को केवल एक थ्रेड द्वारा बुलाया जाना चाहिए जो इस ऑब्जेक्ट के मॉनिटर का मालिक है

यह विधि फेंकता है

  1. IllegalMonitorStateException - यदि वर्तमान थ्रेड ऑब्जेक्ट के मॉनिटर का मालिक नहीं है।

  2. InterruptedException- यदि किसी थ्रेड ने मौजूदा थ्रेड को पहले या जबकि वर्तमान थ्रेड नोटिफिकेशन का इंतजार कर रहा था। जब इस अपवाद को फेंक दिया जाता है, तो वर्तमान थ्रेड की बाधित स्थिति साफ़ हो जाती है।

नींद पर oracle प्रलेखन पृष्ठ से ()Thread वर्ग की विधि :

public static void sleep(long millis)
  1. सिस्टम टाइमर और अनुसूचियों की सटीकता और सटीकता के अधीन, मिलीसेकंड की निर्दिष्ट संख्या के लिए सोने (अस्थायी रूप से निष्पादन को समाप्त) के लिए वर्तमान में निष्पादित धागे का कारण बनता है।
  2. धागा किसी भी मॉनिटर का स्वामित्व नहीं खोता है।

यह विधि फेंकता है:

  1. IllegalArgumentException - यदि मिलिस का मान ऋणात्मक है

  2. InterruptedException- यदि किसी धागे ने वर्तमान धागे को बाधित किया है। जब इस अपवाद को फेंक दिया जाता है, तो वर्तमान थ्रेड की बाधित स्थिति साफ़ हो जाती है।

अन्य महत्वपूर्ण अंतर:

wait()एक गैर-स्थैतिक विधि (उदाहरण विधि) है, जो स्टैटिक विधि sleep()(वर्ग विधि) के विपरीत है ।


1

wait()को एक सिंक्रोनाइज़ की गई विधि के sleep()अंदर दिया जाता है जबकि एक गैर-सिंक्रोनाइज़्ड विधि के अंदर दिया जाता है क्योंकि wait()विधि ऑब्जेक्ट पर लॉक रिलीज़ करती है लेकिन sleep()या yield()रिलीज़ नहीं करती है lock()


sleep()एक synchronizedब्लॉक या विधि के अंदर हो सकता है । उत्तर कुछ नहीं समझाता।
user207421

1
  • विधि wait(1000)वर्तमान थ्रेड को एक सेकंड तक सोने का कारण बनती है ।
    • यदि यह notify()याnotifyAll() विधि कॉल प्राप्त करता है तो एक थ्रेड 1 सेकंड से कम सो सकता है ।
  • कॉल sleep(1000)वर्तमान थ्रेड को ठीक 1 सेकंड के लिए सोने का कारण बनता है ।
    • इसके अलावा सोने का धागा किसी भी संसाधन को बंद नहीं करता है । लेकिन वेटिंग थ्रेड करता है।

1
sleep(1000)वास्तव में 1 सेकंड के लिए सोने की गारंटी नहीं देता है। यह पहले बाधित हो सकता है।
लुसियो

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

1

वास्तव में, यह सब जावा डॉक्स में स्पष्ट रूप से वर्णित है (लेकिन मुझे जवाब पढ़ने के बाद ही पता चला)।

http://docs.oracle.com/javase/8/docs/api/index.html :

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

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

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