2011-08-22 12 views
5

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

टी 2 वह है जो बाधा भेजता है।

मैं चल रहे टी 1 को रोकने में असमर्थ हूं, टी 1 को इंटरप्टेड एक्सेप्शन नहीं मिलता है।

मुझे क्या याद आ रही है?

Executor exec1 = Executors.newFixedThreadPool(1); 

    // task to be interrupted 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       System.out.println("starting uninterruptible task 1"); 
       Thread.sleep(4000); 
       System.out.println("stopping uninterruptible task 1"); 
      } catch (InterruptedException e) { 
       assertFalse("This line should never be reached.", true); 
       e.printStackTrace(); 
      }    
     }   
    }; 
    final Thread t1 = new Thread(runnable); 


    // task to send interrupt 
    Runnable runnable2 = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Thread.sleep(1000); 
       t1.interrupt(); 
       System.out.println("task 2 - Trying to stop task 1"); 
       Thread.sleep(5000); 

      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      }    
     }   
    }; 
    Thread t2 = new Thread(runnable2); 

    exec1.execute(t1); 
      t2.start(); 
    t2.join(); 

उत्तर

3

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

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

+0

धन्यवाद BegemoT। यह समझ में आता है। – portoalet

+0

begemot यह सही मिला है –

0

Thread.interrupt कॉलिंग आवश्यक रूप से InterruptedException फेंक नहीं है निष्पादक धागा बीच में करने के लिए,

final ExecutorService exec1 = Executors.newFixedThreadPool(1); 
final Future<?> f = exec1.submit(runnable); 
... 
f.cancel(true); 
+0

इसके साथ समस्या यह है कि 'रननेबल' अब दो बार निष्पादित किया जाएगा: एक बार थ्रेड पूल के माध्यम से, और एक बार थ्रेड 't1' के माध्यम से। –

+0

मैं थ्रेड निष्पादित करने के लिए निष्पादक का उपयोग कर रहा हूँ। – portoalet

+0

'अंतिम भविष्य f = exec1.submit (runnable); f.cancel (true);' –

0

। यह थ्रेड की बाधित स्थिति को सेट कर सकता है, जिसे Thread.interrupted() या Thread.isInterrupted द्वारा मतदान किया जा सकता है।

अधिक जानकारी के लिए http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt() देखें।

+0

आप गलत थे, दस्तावेज़ीकरण को ध्यान से पढ़ें .. अगर इंटरप्ट किए गए थ्रेड सो रहे हैं तो intterupt विधि बाधित अपवाद का कारण बनता है .. –

+0

.. । अगर बाधित थ्रेड सो रहा है ... मेरा यही मतलब था, शायद थ्रेड सोते समय सो नहीं रहा है। – mort

+0

लेकिन सवाल पर धागा राज्य सो रहा है .. –

3

आपकी गलती यह है कि आप Thread को ThreadPool पर निष्पादित करने का प्रयास कर रहे हैं।

यह प्रकट होता है काम करने के लिए, क्योंकि ThreadRunnable लागू करने के लिए होता है, लेकिन क्योंकि धागा केवल एक Runnable के रूप में इस्तेमाल किया जा रहा है और एक Thread रूप में शुरू किया नहीं है, #interrupt() तरह के तरीकों बुला वांछित असर नहीं होगा।

यदि आपको अभी भी थ्रेड पूल का उपयोग करने की आवश्यकता है, तो आपको FutureTask जैसी कक्षा का उपयोग करना चाहिए। Runnable को FutureTask में लपेटें, और उसके बाद कार्य को थ्रेड पूल पर सबमिट करें। फिर, जब आप कार्य को बाधित करना चाहते हैं, तो futureTask.cancel(true) पर कॉल करें।

1

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

भले ही आपने Thread ऑब्जेक्ट सबमिट किया हो, लेकिन निष्पादक निश्चित थ्रेड पूल द्वारा बनाए गए थ्रेड का उपयोग करेगा। इस प्रकार संदर्भ t1 के साथ धागा वह धागा नहीं है जिसमें आपका कार्य निष्पादित किया जा रहा है। इसलिए t1.interrupt() पर कॉल करना कुछ भी नहीं करने वाला है।

ठीक से यह करने के लिए जिस तरह से करने के लिए एक ExecutorService का उपयोग करें और submit() का प्रयोग कर एक Runnable/Callable वस्तु प्रस्तुत करने के लिए किया जा सके। यह Future लौटाएगा जो cancel() विधि का खुलासा करता है जिसका उपयोग कार्य को रद्द करने के लिए किया जा सकता है।

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