2010-01-21 14 views
5

मैं अपने कार्यक्षेत्र द्वारा लौटाए गए फ़्यूचर्स ऑब्जेक्ट्स की एक सूची प्रबंधित करना चाहता हूं।
मैंने इसजावा थ्रेड - अजीब Thread.interrupted() और future.cancel (सत्य) व्यवहार

List<Future<String>> list 

void process(ProcessThis processThis) {  
    for (...) { 
     Future<String> future = taskExecutor.submit(processThis); 
     list.add(future) 
    } 
} 


void removeFutures() { 
    for(Future future : list) { 
     assert future.cancel(true); 
} 

ProcessThis की तरह कुछ एक काम है कि Thread.interrupted के लिए लागू करता है प्रतिदेय < स्ट्रिंग> और चेक() की स्थिति

public String call() { 
     while (true) { 
      if (Thread.interrupted()) { 
       break; 
      } 
      doSomething(); 
     } 
    } 

अब समस्या यह है है कि केवल के एक सबसेट समवर्ती धागे 'सत्य' लौट रहे हैं जब Thread.interrupted() कहा जाता है।
हटाए गए फ्यूचर्स() में दिए गए हर क्षेत्र को हटाए गए भविष्य के लिए सत्य लौटाता है (मैंने जांच की है() और पूर्ण() है।
बाधित होने वाली थ्रेड की संख्या यादृच्छिक है। 15 से अधिक चलने वाले थ्रेड कभी-कभी 13 बाधित होते हैं, कभी-कभी 2 ...
मैं वास्तव में समझ नहीं पा रहा हूं कि समस्या कहां है। अगर मैं भविष्य को कॉल करता हूं। (सच) और यह सच हो जाता है ... और फिर मैं Thread.interrupted (इसे केवल एक बार कहा जाता है) की जांच करता हूं, मुझे उम्मीद है इस रूप में अच्छी तरह से सच लौटने के लिए।
मैं क्या याद आ रही है की कोई भी विचार?

मैं निर्माण जावा 1.6.0_02-B05 पर हूँ

उत्तर

2

कम से कम, आप interr बहाल करना चाहिए uption झंडा taskExecutor धागा रुकावट के बारे में पता करने के लिए:

public String call() { 
    while (true) { 
     if (Thread.interrupted()) { 
      Thread.currentThread().interrupt(); 
      break; 
     } 
     doSomething(); 
    } 
} 
+0

आपकी प्रतिक्रिया के लिए धन्यवाद। ऐसा करने का क्या मतलब है? यदि Thread.interrupted() सत्य लौटाता है तो मैं चक्र चक्र तोड़ता हूं और मैं मूल रूप से धागे को मारता हूं। समस्या यह है कि कभी-कभी Thread.interrupted() 'झूठा' देता है भले ही संबंधित भविष्य.cancel (सत्य) सच हो। आपके द्वारा संपादित की गई रेखा उस समय तक भी नहीं पहुंच सकती है। – marts

+0

फिर बाधा झंडा शायद 'doSomething()' में कहीं खो गया है (इसी कारण से - कुछ ध्वज को रीसेट करता है और इसमें पुनर्स्थापित नहीं होता है)। यही है, मेरे उत्तर में नमूना एक बुनियादी सिद्धांत है जिसका उपयोग खोए गए इंटरप्ट्स – axtavt

+0

से बचने के लिए किया जाना चाहिए यदि ऐसा है ('खोए गए इंटरप्ट्स से बचें') तो क्या मैं सिर्फ Thread.currentThread() की तरह कुछ उपयोग नहीं कर सकता। IsInterrupted() के बजाय हर बार जब मैं Thread.interrupted() का उपयोग करता हूं तो इंटरप्ट स्थिति को पुनर्स्थापित करना पड़ता है। (बीटीडब्ल्यू के साथ एक बग है: http://stackoverflow.com/questions/2012259/) मैं कुछ करने में बाधा स्थिति से निपट नहीं रहा हूं। – marts

2

एक संभावित समस्या है कि बीच में आता है अक्सर निगल लिया जाता है। तो कहीं doSomething() (या यहां तक ​​कि कक्षा लोडिंग में) में गहराई से, wait() कहकर एक बाधा पकड़ी जा सकती है और फिर 'लापरवाह' कोड से त्याग दिया जा सकता है। इंटरप्ट्स बुराई हैं, आईएमओ।

यह जांचने योग्य हो सकता है कि आप सभी कार्य वास्तव में रद्द होने के समय चल रहे हैं।

6

ध्यान रखें कि Thread.interrupted() वर्तमान बाधित स्थिति देता है और फिर इसे साफ़ करता है, इसलिए सभी भविष्य के आमंत्रण झूठे हो जाएंगे। आप जो चाहते हैं वह शायद Thread.currentThread().isInterrupted() है।

यह भी ध्यान रखें कि future.cancel(true) आमतौर पर केवल तभी वापस आ जाएगा जब कार्य पहले से ही पूरा हो चुका है या रद्द कर दिया गया है। यदि यह सच हो जाता है, तो यह गारंटी नहीं है कि कार्य वास्तव में रद्द कर दिया जाएगा।

doSomething() में क्या हो रहा है? यह संभव है कि रूकाइम अपवाद किसी भी बाधा के कारण कहीं से बच रहा है। क्या आपके पास UncaughtExceptionHandler सेट है? यदि नहीं, तो आपको ThreadFactory को Executor पर पास करने की आवश्यकता होगी जो अपवाद हैंडलर सेट करेगा और किसी भी चूक के अपवाद लॉग करेगा।

+0

मुझे इस बारे में पता है। मैं Thread.interrupted() को थोड़ी देर बाद ही कॉल कर रहा हूं {। वैसे भी अगर यह सच हो जाता है तो मैं तोड़ता हूं; और तुरंत थ्रेड को मार डालें (और मैं कहीं और बाधा को स्पर्श/जांच नहीं करता)। मैं UncaughtExceptionHandler पर एक नज़र डालेंगे। आपकी प्रतिक्रिया के लिए आभार । (बीटीडब्ल्यू थ्रेड.currentThread() में इस बग से अवगत रहें। अंतर्निहित() http://bugs.sun.com/view_bug.do?bug_id=6772683) – marts

+0

वर्तमान में, आप सही ढंग से Thread.interrupted() का उपयोग कर रहे हैं सुरक्षित तरीके से हालांकि, अगर आपको उस विधि द्वारा प्रदान किए गए व्यवहार की आवश्यकता नहीं है, तो आपको इसे किसी और के रूप में उपयोग नहीं करना चाहिए (या आप स्वयं) उस विधि को दोबारा कर सकते हैं जैसे कि Thread.interrupted() को इस तरह से बुलाया जाता है जो बाधा प्रबंधन को अमान्य करता है । Thread.currentThread() का उपयोग करने के लिए यह अधिक सुरक्षित है। अगर आप कर सकते हैं तो अवरुद्ध() है। – Kevin

+0

हाय केविन। आप सही हैं लेकिन जावा लाइसेंस मुद्दे के कारण मैं वर्तमान JVM 1.6.0_02-b05 को अपडेट नहीं कर सकता। मैं एक बहु-प्रोसेसर मशीन पर चल रहा हूं और मेरी जेवीएम पिछली टिप्पणी में जुड़ी हुई बग से प्रभावित हो सकती है (यहां स्टैक ओवरफ्लो http://stackoverflow.com/questions/2012259/ में एक संबंधित पोस्ट है)। अनचाहे अपवाद के बारे में, यदि एक रनटाइम अपवाद से बचने के लिए मैं कल्पना कर सकता हूं कि थ्रेड अपने आप से मर जाता है, है ना? यहाँ मेरी समस्या विपरीत है .. वे रुकते नहीं हैं। (या कम से कम उनमें से एक सबसेट बंद कर दिया गया है) – marts