2010-09-23 15 views
6

मैं एक ऐसा एप्लीकेशन लिख रहा हूं जो एकाधिक समवर्ती कार्यों को जन्म दे। मैं इसे लागू करने के लिए एक थ्रेड पूल का उपयोग कर रहा हूँ।थ्रेडपूल में धागे को कैसे रोकें

ऐसा हो सकता है कि एक घटना होती है जो अमान्य कार्यों में गणना की जाती है। उस स्थिति में, मैं वर्तमान में चल रहे कार्यों को रोकना चाहता हूं, और नए शुरू करना चाहता हूं।

मेरी समस्या: मैं वर्तमान में चल रहे कार्यों को कैसे रोकूं? मैंने जिस समाधान को कार्यान्वित किया है वह कार्य धागे के संदर्भ को संग्रहीत करना है और इस धागे पर interrupt() पर कॉल करना है। डेमो कोड में:

public class Task implements Runnable { 

    private String name; 
    private Thread runThread; 

    public Task(String name) { 
     super(); 
     this.name = name; 
    } 

    @Override 
    public void run() { 
     runThread = Thread.currentThread(); 

     System.out.println("Starting thread " + name); 
     while (true) { 
      try { 
       Thread.sleep(4000); 
       System.out.println("Hello from thread " + name); 
      } catch (InterruptedException e) { 
       // We've been interrupted: no more messages. 
       return; 
      } 
     } 
    } 

    public void stop() { 
     runThread.interrupt(); 
    } 

    public String getName() { 
     return name; 
    } 
} 

और मुख्य विधि है:

public static void main(String args[]) { 
    executorService = Executors.newFixedThreadPool(2); 

    Task t1 = new Task("Task1"); 
    Task t2 = new Task("Task2"); 
    executorService.execute(t1); 
    executorService.execute(t2); 
    executorService.execute(new Task("Task3")); 
    executorService.execute(new Task("Task4")); 

    try { 
     Thread.sleep(12000); 
     t1.stop(); 
     System.err.println("Stopped thread " + t1.getName()); 
     Thread.sleep(8000); 
     t2.stop(); 
     System.err.println("Stopped thread " + t2.getName()); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

यह एक अच्छा समाधान है, या वहाँ एक बेहतर एक धागा पूल में चल रहे धागा बंद करने के लिए तरीका है?

+1

प्लग खींचें;) – sje397

उत्तर

2

आपके ओवरराइड run() विधि में आप हमेशा while(true) के साथ लूप करते हैं। मानक व्यवहार boolean runIndicator होगा जो run() विधि प्रारंभ होने पर सत्य पर सेट होता है, और आपका लूप while(runIndicator) होना चाहिए। आपकी stop() विधि को सरल runIndicator = false सेट करना चाहिए ताकि लूप का अगला पुनरावृत्ति समाप्त हो जाए।

+0

इस कार्यान्वयन में, 'स्टॉप()' विधि को 'this.interrupt()' भी कॉल करना चाहिए। वास्तविक कार्यान्वयन में, ऐसी ही विधि होनी चाहिए जिसका उपयोग आप 'थ्रेड.sleep * (4000)' कॉल के बजाय जो भी भारी उठाने जा रहे हैं उसे रोकने के लिए कर सकते हैं। आप इसे पूरा करने के लिए 'रनइंडिकेटर' के लिए एक बहुत ही समान विधि का उपयोग कर सकते हैं। –

+0

@Erick, 'interrupt() 'चलाने योग्य नहीं है, इसलिए यह संभव नहीं है। 'Thread.currentThread()। Interrupt() 'या तो काम नहीं करेगा क्योंकि स्टॉप() की कॉलिंग किसी अन्य थ्रेड में होती है जिसे आप बाधित करना चाहते हैं। – Thirler

+1

क्षमा करें, मुझे यह नहीं मिला। मैं हमेशा 'रननेबल' के बजाय 'थ्रेड'' बढ़ाता हूं, इसलिए मुझे हमेशा इन चीजों तक पहुंच होती है। मैं वही करूँगा। यह आपके उत्तर में पोस्ट किए गए मामूली थ्रेडसेफ मुद्दे को भी हल करेगा। –

3

आपके दृष्टिकोण के पीछे विचार कई सही समाधानों में से एक है। Dealing with InterruptedException आपको इंटरप्ट तंत्र का उपयोग करने के तरीके पर एक महान रैंड डाउन देता है। जब आप लंबी गणना करते हैं तो यह तंत्र मुख्य रूप से उपयोगी होता है। एक और बात ध्यान में रखना यह है कि अन्य पुस्तकालयों के लिए गाइड आपके द्वारा किए गए कार्यों को न करने के द्वारा आपके इंटरप्ट तंत्र को खराब करना संभव है (जब वे इसे संभाल नहीं लेते हैं तो इंटरप्ट स्थिति को रीसेट नहीं करते हैं)।

ध्यान दें कि आपकी Task कक्षा थ्रेड-सुरक्षित नहीं है। currentThread को सहेजने से पहले आप कार्य को रोक सकते हैं, जो एक NullPointerException प्रदान करेगा।

एक बहुत सरल दृष्टिकोण (यह तथापि और अधिक सामान्य है) एक volatile boolean चर running और बजाय एक while(true) पाश एक while(running) दृष्टिकोण करने के स्थापित करने के लिए है।

FutureTask तंत्र को देखने के लिए एक और चीज है, क्योंकि इसमें पहले से ही एक रद्द करने वाली तंत्र है जो इंटरप्ट तंत्र का उपयोग करती है।

1

निष्पादक सेवा.शूटडाउन() और निष्पादक सेवा.शूटडाउन अब() को थ्रेड पूल को एप्लिकेशन से बाहर निकलने के लिए बंद करने के लिए उपयोग किया जाना चाहिए। ExecutorService देखें।

वर्तमान में चल रहे थ्रेड को समाप्त करने के लिए क्वर्वकी का उत्तर देखें। चल रहा है, तो बाधित हो सकते हैं -

+4

वह एक ही धागा बंद करना चाहता है, पूरे पूल में नहीं। –

+0

वह उत्तर Qwerky द्वारा दिया गया है। लेकिन थ्रेड पूल को बंद करना भी आवेदन से बाहर निकलने के लिए भी आवश्यक है। –

2

आपको लगता है कि भविष्य

  Future<?> future = exec.submit(new Runnable() { 
     while (true){ 
     try{ 
      obj.wait(); 
     }catch(InterruptedException e){ 
      System.out.println("interrupted"); 
      return; 
     } 
     }); 
     future.cancel(true); 

बूलियन के लिए एक संदर्भ पकड़ कर इसे रोकने के कर सकते हैं के लिए है।

मैंने परीक्षण किया और उस धागे से बाधित अपवाद प्राप्त किया।

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

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