WAIT और BLOCKED थ्रेड राज्यों के बीच अंतर


101

धागा राज्य WAIT और धागा राज्य BLOCKED में क्या अंतर है?

Thread.State प्रलेखन :

अवरुद्ध
एक धागा जो एक मॉनिटर लॉक के इंतजार में अवरुद्ध है, इस स्थिति में है।

वेटिंग
एक थ्रेड जो किसी अन्य थ्रेड के लिए अनिश्चित रूप से प्रतीक्षा कर रहा है एक विशेष क्रिया करने के लिए इस स्थिति में है

मुझे अंतर नहीं समझाता।


इस उत्तर में चेक उत्तर stackoverflow.com/questions/2534147/java-thread-wait-blocked भी यह लिंक आगे स्पष्टीकरण प्रदान कर सकता है geekexplains.blogspot.cz/2008/07/…
अब्दुल

@Addul geekexplains लिंक का कहना है कि एक धागा Object.wait () को कॉल करके एक अवरुद्ध स्थिति में जा सकता है जो कि सही नहीं है?
पांच

oracle docs docs.oracle.com/javase/6/docs/api/java/lang/… के अनुसार : निम्न विधियों में से एक को कॉल करने के कारण थ्रेड प्रतीक्षा अवस्था में है: Object.wait with no timeout, Thread.join बिना टाइमआउट के साथ, LockSupport.park
अब्दुल

रिकॉर्ड के लिए, मुझे लगता है कि @ फ्लावियो का जवाब अंकित के मामले में थोड़ा बेहतर है, अगर आप बदलाव पर विचार कर सकते हैं।
ग्रे

जवाबों:


80

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

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

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


2
आपने इसे बहुत बेहतर तरीके से समझाया क्योंकि आपने उस क्रम को समझाया जिसमें एक धागा उन दो राज्यों तक पहुँचता है जो इसे अलग करने की स्थिति में दोनों में से प्रत्येक को स्पष्ट करने की तुलना में स्पष्ट करता है (जो कि "मोर थान फाइव" के उत्तर द्वारा किया गया है
कुमार मनीष

7
उन सभी के लिए, जो आश्चर्यचकित करते हैं कि वेब दावा में पाए गए अधिकांश (सभी?) स्टेट डायग्राम, कि अधिसूचित () / InformAll () परिणाम BLOCKED के बजाय RUNNABLE में हैं: stackoverflow.com/questions/2837492/-
पीटर

मान लें कि केवल एक धागा है और कुछ समय मिलिस में इंतजार किया; अब क्या यह संभव है कि एक धागा सीधे चल रहे राज्य से चल सकने योग्य राज्य में जा सके? चूँकि केवल एक ही धागे से कोई अन्य धागा यहाँ लॉक नहीं होता है?
कानूनगावेल सुगुमार

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

2
आपका उत्तर अच्छा है, लेकिन यह बिल्कुल स्पष्ट नहीं करता है कि आप किसी भी लॉक को प्राप्त करने का प्रयास करते हुए कभी भी अवरुद्ध स्थिति में प्रवेश कर सकते हैं। इसका सिग्नल / नोटिफिकेशन से कोई लेना-देना नहीं है।
ग्रे

90

अंतर अपेक्षाकृत सरल है।

में BLOCKEDराज्य, एक धागा एक में प्रवेश करने के बारे में है synchronizedब्लॉक है, लेकिन वहाँ एक और धागा वर्तमान में एक के अंदर चल रहा है synchronizedएक ही वस्तु पर ब्लॉक। पहले थ्रेड को इसके ब्लॉक से बाहर निकलने के लिए दूसरे थ्रेड का इंतजार करना होगा।

में WAITINGराज्य, एक धागा एक और धागे से सिग्नल की प्रतीक्षा कर रहा है। यह आमतौर पर कॉल करके Object.wait(), या होता है Thread.join()। थ्रेड तब तक इस स्थिति में रहेगा जब तक कि कोई अन्य थ्रेड कॉल नहीं करता Object.notify(), या मर जाता है।


2
क्या यह कहना सही है कि केवल एक धागा ही इसे प्रतीक्षा में जा सकता है? क्या थ्रेड-बी कभी थ्रेड-ए बना सकता है?
पांच

1
आप शायद ही कभी Object.wait()सीधे उपयोग करते हैं, लेकिन आप WAITINGराज्य में अधिक उच्च-स्तरीय संगामिति निर्माणों का उपयोग करके भी समाप्त होते हैं - जैसे ताले, अवरुद्ध कतारें, आदि ... मोटे तौर पर, जब भी दो थ्रेड्स को समन्वय करना होता है।
फ्लावियो

1
व्यक्तिगत अनुभव से, IO की प्रतीक्षा कर रहे धागे (जैसे सॉकेट से पढ़ना) RUNNINGराज्य में हैं।
फ़्लावियो

4
Java8 के लिए doc Thread.Stateकहता है, "... ये राज्य वर्चुअल मशीन राज्य हैं जो किसी भी ऑपरेटिंग सिस्टम थ्रेड स्टेट्स को प्रतिबिंबित नहीं करते हैं।" दूसरे शब्दों में, JVM जावा कोड को चलाने वाले थ्रेड के बीच अंतर के बारे में परवाह नहीं करता है, एक थ्रेड जो सिस्टम कॉल के लौटने का इंतजार कर रहा है, या एक थ्रेड जो टाइम स्लाइस का इंतजार कर रहा है। वे सभी RUNNABLEजहां तक ​​जेवीएम का सवाल है।
सोलोमन स्लो

3
यह जोड़ना अच्छा हो सकता है कि जब WAITINGराज्य से एक धागा चलता है , तो उसे पहले BLOCKEDराज्य में जाना चाहिए जब तक कि वह उस ऑब्जेक्ट से जुड़े लॉक का अधिग्रहण नहीं कर सकता है जिस पर वह इंतजार कर रहा था।
ग्रे

22

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

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

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

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


क्या इसलिए कि मॉनिटर ऑब्जेक्ट पर सूचित () कॉल करने के लिए कुछ अन्य थ्रेड जिम्मेदारी है?
बेरीम्बोलो

@berimbolo: मुझे समझ नहीं आ रहा है कि आप क्या पूछ रहे हैं
नाथन ह्यूजेस

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

@berimbolo: प्रतीक्षा थ्रेड अंतत: एक सूचना द्वारा जाग्रत हो जाता है। अनुसूचक तय करेगा कि कौन सा प्रतीक्षा धागा अधिसूचित किया जाए।
नाथन ह्यूजेस

कुछ मायने रखता है, आप स्पिन-लॉक कह रहे हैं, BLOCKED खुराक का मतलब यह नहीं है कि यह स्पिन-लॉक है
फ्रैंक झांग

16

धागा डंप की व्याख्या के लिए सरलीकृत परिप्रेक्ष्य:

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

1
मुझे आपका स्पष्टीकरण पसंद है। ठीक यही मैं अभी थ्रेड डंप का विश्लेषण करने की कोशिश कर रहा हूं :)
श्रीधर सरनोबत

@MuhammadGelbana हाँ, आप सही हैं, मैंने टिप्पणी हटा दी है।
एरिक वांग

1
आपका RUNNABLEकहना बिलकुल सही नहीं है। यह जावा रन कतार में हो सकता है लेकिन निष्पादित नहीं हो रहा है या यह जावा कोड को निष्पादित कर सकता है। यह देशी-भूमि को कॉल करने की आवश्यकता नहीं है।
ग्रे

1

ब्लॉक किया गया - आपका धागा थ्रेड जीवन चक्र की चल अवस्था में है और ऑब्जेक्ट लॉक प्राप्त करने की कोशिश कर रहा है। प्रतीक्षा करें- आपका धागा थ्रेड जीवन चक्र की प्रतीक्षा अवस्था में है और थ्रेड के रन करने योग्य स्थिति में आने के लिए सूचित संकेत की प्रतीक्षा कर रहा है।


-1

इस उदाहरण को देखें:

धागा राज्यों का प्रदर्शन।

/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
  Also when join() is called.
TIMED_WAITING- when below methods are called:
 Thread.sleep
 Object.wait with timeout
 Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{

public static void main(String[] args) throws InterruptedException {
    Object obj= new Object();
    Object obj2 = new Object();
    Thread3 t3 = new Thread3(obj,obj2);
    Thread.sleep(1000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
            ",when Wait() is called & waiting for notify() to be called.");
    Thread4 t4 = new Thread4(obj,obj2);
    Thread.sleep(3000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
    System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}

}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        try {
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
            obj.wait();             
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
            synchronized (obj2) {
                cnt++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
        obj.notify();
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
    }
    synchronized (obj2) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

कोड के लिए धन्यवाद, लेकिन मैं आपको एक पाठ उत्तर देना चाहूंगा और फिर एक छोटा कोड ब्लॉक दिखाऊंगा ।
ग्रे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.