2010-08-03 12 views
19

इस प्रतीक्षा घोषणा करने के बाद:सूचित करते समय प्रतीक्षा करें (लंबी टाइमआउट) अधिसूचना या समय समाप्ति के लिए बाहर निकलें?

public final native void wait(long timeout) throws InterruptedException; 

यह टाइमआउट द्वारा InterruptedException से बाहर निकलने सकता है, या, या क्योंकि सूचित करें/NotifyAll विधि एक और धागा में बुलाया गया था, अपवाद को पकड़ने के लिए आसान है, लेकिन ...

वहाँ

यह जानने का कोई तरीका है कि बाहर निकलने का कारण टाइमआउट था या अधिसूचित था?

संपादित करें:

यह एक मुश्किल रास्ता है कि, काम कर सकता था (हालांकि मैं यह पसंद नहीं है)

  long tBefore=System.currentTimeMillis(); 
      wait(TIMEOUT); 
      if ((System.currentTimeMillis() - tBefore) > TIMEOUT) 
      { 
       //timeout 
      } 
+2

मुझे एक समान आवश्यकता थी और मेरे मामले में यह पता चला कि 'सेमफोर' बेहतर अनुकूल था; 'Semaphore.tryAququire (लंबी टाइमआउट, टाइम यूनिट यूनिट) 'टाइमआउट समाप्त होने पर' 'झूठा' लौटाता है। – Santosh

+0

सेमफोर तब तक काम करेगा जब तक आपको प्रतीक्षा करने की क्षमता न हो, जो सेमाफोर सार्वजनिक अनुबंध द्वारा समर्थित नहीं है। –

उत्तर

7

आप दोनों के बीच अंतर नहीं कर सकते जब तक कि आप कुछ अतिरिक्त प्रदान करना है कोड। एक ThreadLocalBoolean कि केवल notify()

पर true के लिए निर्धारित है लेकिन पहले आपको यह सुनिश्चित कर लें चाहिए जोड़कर उदाहरण के लिए अपने तर्क इस भेदभाव की आवश्यकता है।

+4

ओपी पहले ही जानता था कि एक अपवाद फेंक दिया नहीं जाएगा और एक टाइमआउट और अधिसूचना के बीच अंतर करना चाहता है। यह उस अंत तक कोई उपयोगी जानकारी प्रदान नहीं करता है। –

+1

धन्यवाद, मैंने ओपी को गलत समझा। अभी अपडेट किया गया – Bozho

+0

रीराइट करने के लिए +1, और हां एक बूलियन एक सिंक्रनाइज़ विधि है जिसका मैं अब उपयोग कर रहा हूं –

1

अपवाद और समय पर अपवाद को फेंक दिया नहीं गया है।

मुझे लगता है कि Object.wait() का उपयोग करने के बजाय java.lang.concurrent पैकेज सिंक्रनाइज़ेशन ऑब्जेक्ट पर भरोसा करना बेहतर है।

12

यही सवाल का जवाब नहीं है, लेकिन यह शायद आपकी समस्या का समाधान होगा: उच्च स्तर संगामिति तंत्र का प्रयोग करें। प्रतीक्षा करें/अधिसूचना आमतौर पर आप चाहते हैं की तुलना में अधिक निम्न स्तर है, इस कारण से कई अन्य लोगों के बीच।

उदाहरण के लिए, यदि आप BlockingQueue.poll(long, TimeUnit) उपयोग कर रहे थे, तो आप यदि परिणाम अगर आप का समय समाप्त हो पता करने के लिए रिक्त है जांच कर सकता है।

16

एक और कारण है कि अधिसूचना वापस लौट सकती है: नकली wakeup। यह एक असंभव लेकिन संभव बात है, क्योंकि कुछ हार्डवेयर/ओएस संयोजनों पर नकली वेकअप को रोकना बहुत महंगा है।

इस आप हमेशा() एक पाश में इंतजार कॉल करने के लिए और शर्त यह है कि आप के लिए इंतजार कर रहे हैं की फिर से जांच की है वजह से

। इस काम के दौरान एक ही समय में टाइमआउट की जांच करना आसान है।

विवरण के लिए मैं पुस्तक "जावा कंसुरेंसी इन प्रैक्टिस" की अनुशंसा करता हूं। और उच्च स्तरीय संरचनाओं का उपयोग करना जो आपके लिए यह सब सही होगा।

+0

+1 मुझे उन नकली जागरूकता –

2

सीधे बताने का कोई तरीका नहीं है - यानी, आपको यह निर्धारित करने के लिए अतिरिक्त कोड जोड़ना होगा। अक्सर जब आप प्रतीक्षा करते हैं(), आप कुछ ऐसा होने की प्रतीक्षा कर रहे हैं जो किसी ऑब्जेक्ट की स्थिति को किसी तरह से बदलता है - उदा। शायद एक बूलियन चर सेट करके। यदि ऐसा है, तो आप यह देखने के लिए कि क्या घटना हुई है, या आप केवल समय समाप्त होने पर उस चर के राज्य की जांच कर सकते हैं। या आप System.currentTimeMillis() के मान को देख सकते हैं कि यह समय बीतने के समय से अधिक या बराबर है - यदि ऐसा है, तो यह एक सुराग होगा जो आपने संभवतः समाप्त कर दिया है (हालांकि यह पूर्ण गारंटी नहीं है)। या यदि विलुप्त समय टाइमआउट अवधि से कम है तो निश्चित रूप से आप का समय समाप्त नहीं हुआ है। क्या उससे मदद हुई?

+0

में ध्यान में रखेगा, मैं वास्तव में वर्तमान टाइममिलिस() का उपयोग कर रहा हूं, लेकिन मैं सोच रहा था कि –

+0

@ हर्नान एशे कुछ बेहतर तरीका है जैसा कि मैंने अपने उत्तर में रखा है, इसकी पूर्ण गारंटी नहीं है। यदि आप बता सकते हैं, तो आप यह पहचानना क्यों चाहते हैं कि यह समय-समय पर है या नहीं? हम कुछ समाधान की तलाश कर सकते हैं। – YoK

+0

हाँ, मुझे पता है कि यह एक बहुत अच्छा दृष्टिकोण नहीं है, मैं इसे लूप के लिए उपयोग करता हूं (सत्य) {प्रतीक्षा (टाइमआउट); अन्य कार्य..; } ताकि जब प्रतीक्षा वास्तव में अधिसूचित की गई हो तो लूप से बाहर निकल सकता है, उदाहरण के लिए यदि इंतजार बूलियन लौटाएगा, तो यह कुछ होगा (सत्य) {if (प्रतीक्षा करें (टाइमआउट)) तोड़ें; अन्य कार्य..; } वैसे भी मैं इसे सभी वर्गों के भीतर समेकित कर दूंगा और इस ध्वज की सेटिंग के साथ समानांतर में प्रतीक्षा/अधिसूचित करने के लिए सिंक्रनाइज़ विधि के साथ ध्वज –

3

System.currentTimeMillis() का उपयोग न करें, इसके बजाय System.nanoTime() का उपयोग करें।

पहला व्यक्ति पूर्ण समय (सिस्टम घड़ी के आधार पर) का आकलन करता है और सिस्टम समय बदल जाने पर उत्सुक परिणाम हो सकते हैं। उदाहरण के लिए: यदि 5 घंटे की प्रतीक्षा में एक घंटे की अवधि हो सकती है, तो घड़ी एक घंटे तक पिछली बार चली जाती है, या घड़ी के आगे बढ़ने पर 0 मिनट के बाद 10 मिनट का इंतजार किया जाएगा।

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

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