2012-07-28 21 views
6

में स्लीप विकल्प मुझे बताया गया है कि Thread.Sleep() का उपयोग करना एक खराब समाधान है जब कोई सिंक्रनाइज़ विधि में कार्यों के लूप के भीतर कुछ समय अंतराल बनाना चाहता है।थ्रेड। जावा

दूसरी तरफ, मेरे पास दो अलग-अलग धागे हैं जो मेरे प्रोग्राम के चलने वाले समय में सक्रिय हैं और एक साझा ऑब्जेक्ट भी सक्रिय हैं और जब मैं उस साझा ऑब्जेक्ट में ऑब्जेक्ट.वाइट (लम्बा) का उपयोग करता हूं, तो यह मेरे जीयूआई को स्थिर करता है कुछ समय के लिए।

इस समस्या के लिए बेहतर समाधान क्या होगा?


अद्यतन कोड का यह हिस्सा धागे जो जीयूआई में शुरू हो रहा है में से एक सहित जाता है:

class temperatureUp extends Thread { @Override public void run() { while(true) { try { GBC.increaseTemp(); updateSystemStatus(); } catch(Exception ex) { StringWriter w = new StringWriter(); ex.printStackTrace(new PrintWriter(w)); txtLog.setText(w + "\n" + txtLog.getText()); } } } };

और इस साझा वस्तु में सिंक्रनाइज़ विधि, जीबीसी है:

public synchronized void increaseTemp() throws InterruptedException{ 
    // don't increase the temperature if the boiler 
    // is not turned on... 
    while (!isBoilerOn) 
     wait(); 

    // increase the current temperature 
    if ((currentTemp + 1) < MAX_TEMP && currentTemp < desiredTemp) { 
     Thread.sleep(2000); ///what should put here if not thread sleep? 
     currentTemp ++;  
     updateGasBoilerStatus(); 
    } 
} 
+1

आप [घटना भेजने धागा] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) प्रतीक्षा करनी पड़ सकती किया जाना चाहिए। क्या आप अपने धागे को कैसे शुरू करते हैं और जब आप प्रतीक्षा() कॉल करते हैं, तो कोड में एक छोटा सा उदाहरण प्रदान कर सकते हैं? – theon

+1

पर एक नजर डालें [ 'SwingWorker'] (http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html)। साथ ही, यह जानने के लिए ['this answer'] (http://stackoverflow.com/a/11546203/597657) देखें। –

+0

@theon मैंने पोस्ट को अपडेट किया और कोड के कुछ हिस्से को जोड़ा। – Afflatus

उत्तर

4

आप synchronize कथन के दायरे को कम कर सकते हैं। उदाहरण के लिए आप पूरे विधि पर सिंक्रनाइज़ किए जाने

public synchronized void foo() 

आप संशोधक को हटाने और एक तुल्यकालन ब्लॉक बजाय

synchronized (this) { 
    // ... 
} 

का उपयोग करें और इस ब्लॉक की Thread.sleep() बाहर ले जाने के यदि संभव हो सकता है। केवल उन बयानों पर सिंक्रनाइज़ करें जो साझा डेटा के राज्यों को संशोधित करते हैं।

स्विंग के बारे में बहुत सारी थ्रेडिंग समस्याएं Event Dispatcher Thread से संबंधित हैं और इसे आसानी से हल किया जा सकता है। मैं आपको इसे पढ़ने की सलाह देते हैं।

थोड़ा सा पृष्ठभूमि, क्यों आप एक तुल्यकालन ब्लॉक के अंदर Thread.sleep() नहीं बुलाना चाहिए:

स्लीपिंग या जब एक ताला पकड़े इंतजार कर। लॉक के साथ थ्रेड स्लीप कॉलिंग अन्य धागे को समय के लिए प्रगति करने से रोक सकती है और इसलिए संभावित रूप से गंभीर लचीला खतरे है। कॉलिंग ऑब्जेक्ट.वेट या कंडीशन.एइट दो लॉक के साथ एक समान खतरे का निर्माण करता है। [JCIP]

+1

धन्यवाद, मैं घटना डिस्पैच थ्रेड पर लेख पढ़ सकते हैं और मैं एक और सवाल किया था मामले में आप को वापस मिल जाएगा। – Afflatus

+0

@Elham आपके मामले में मुझे लगता है कि स्विंग * में * संगामिति के पूरे अध्याय में मदद मिलेगी, क्योंकि EDT अद्यतन करने स्विंग घटकों के लिए है और अपने तुल्यकालन समस्या अपने मॉडल के राज्यों को संशोधित करने के बारे में है। –

+0

वास्तव में अद्यतन भाग ठीक काम करता है। समस्या मैं इसे प्रत्येक अपडेट के बाद इंतजार है ताकि उपयोगकर्ता प्रक्रिया है जो धागे द्वारा किया जाता है चरण दर चरण के परिणाम देखना होगा बनाने के लिए चाहते हैं। – Afflatus

7

सिंक्रनाइज़ विधि के अंदर सोएं मत! जीयूआई घटना हैंडलर/तरीकों में इंतजार मत करो!

सिंक्रनाइज़ किए गए कार्यों को विभाजित करें ताकि नींद() कॉल को GUI थ्रेड संदर्भ में नहीं कहा जा सके।

शायद दूसरे बिट के लिए InvokeLater() का उपयोग करें।

+0

संशोधित करते हैं, मैंने पहले से ही जीयूआई में नींद कमांड को निष्क्रिय कर दिया है। सिंक्रनाइज़ विधि एक और कक्षा में है, जैसा कि मैंने कहा है कि यह एक साझा-वस्तु है जिसका उपयोग एक ही समय में दो अलग-अलग धागे द्वारा किया जा रहा है। – Afflatus

0

मैं मॉनीटर का उपयोग करता हूं: http://www.artima.com/insidejvm/ed2/threadsynch4.html शायद सूचित या अधिसूचित करने के साथ आप इसे हल कर सकते हैं। सौभाग्य!

+0

धन्यवाद, लेकिन बात इंतज़ार कर रहे और धागा कार्यक्रम में सिर्फ ठीक काम कर रहा अधिसूचित करने है। मेरी समस्या यह है कि मैं इसे बनाना चाहता हूं ताकि उपयोगकर्ता के देखने के लिए जीयूआई में वृद्धि प्रस्तुति धीमी हो जाएगी। – Afflatus

0

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

synchronized(this){ 
    //... 
} 
+0

ठीक है, धन्यवाद, लेकिन यह मेरे प्रश्न का उत्तर कैसे होगा ?! – Afflatus

+0

और मेरी सिंक्रनाइज़ विधि में केवल तीन क्रियाएं रखी गई हैं जो इस अनुक्रम में समान लॉक के तहत आवश्यक हैं। मैं अब और दायरे को कम नहीं कर सकता। – Afflatus

-1

आप इस निम्नलिखित कोड की कोशिश कर सकते सिंक्रनाइज़: देरी के रूप में

public static void delay(int waitTime) { 
     long endTime = System.currentTimeMillis() + (waitTime * 1000); 
     while (System.currentTimeMillis() < endTime) {} 
    } 

कॉल (5)। और नियंत्रण 5 सेकंड तक इंतजार करेगा।

+0

कृपया इसका उपयोग न करें, यह बहुत गन्दा है। Java.util.Timer का उपयोग करने के लिए एक वैकल्पिक होगा –

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