2010-07-07 17 views
59

मैंने एक धागा लिखा, इसे निष्पादित करने में बहुत अधिक समय लग रहा है और ऐसा लगता है कि यह पूरी तरह से नहीं किया जाता है। मैं धागे को गहराई से रोकना चाहता हूं। कोई मदद ?जावा थ्रेड को शानदार तरीके से कैसे रोकें?

उत्तर

66

अच्छा जिस तरह से यह धागा एक boolean चर द्वारा सुरक्षित की run() की तरह कुछ है और बाहर से true के लिए सेट जब आप इसे बंद करना चाहते हैं, है क्या करने के लिए:

class MyThread extends Thread 
{ 
    volatile boolean finished = false; 

    public void stopMe() 
    { 
    finished = true; 
    } 

    public void run() 
    { 
    while (!finished) 
    { 
     //do dirty work 
    } 
    } 
} 

एक बार एक समय पर stop() विधि मौजूद थी, लेकिन प्रलेखन के अनुसार

यह विधि स्वाभाविक रूप से असुरक्षित है। Thread.stop के साथ थ्रेड को रोकने से यह उन सभी मॉनीटर को अनलॉक कर देता है जो इसे लॉक कर चुके हैं (अनचेक थ्रेडडिथ अपवाद के प्राकृतिक परिणाम के रूप में स्टैक को प्रसारित करते हैं)। यदि इन मॉनीटरों द्वारा पहले संरक्षित वस्तुओं में से कोई भी एक असंगत स्थिति में था, तो क्षतिग्रस्त वस्तुएं अन्य धागे के लिए दृश्यमान हो जाती हैं, संभावित रूप से मनमाना व्यवहार में परिणामस्वरूप।

है यही कारण है कि आप एक गार्ड होना चाहिए ..

+2

जॉन स्कीट की बार्ट के उत्तर पर टिप्पणी देखें - यह आपके लिए भी लागू होता है। –

+0

यदि आप अपना "गंदा काम" धागा कर रहे हैं तो "समाप्त" परिवर्तन समाप्त नहीं होगा, तो आपको आवधिक जांच करना होगा, उदाहरण के लिए लूप में नींद (एक्स) के साथ, कुछ ऐसा जो आपको अनुशंसित नहीं करता है और आपको देता है एक बुरा प्रदर्शन, तो वास्तव में यह एक अच्छा अपमान है? –

+0

हम एक धागे को शानदार ढंग से छोड़ने के बारे में बात कर रहे हैं। अपने गंदे काम के बीच में छोड़ने के लिए धागे को मजबूर करना इसे करने का एक शानदार तरीका नहीं है। आपको अगली पुनरावृत्ति के लिए हमेशा इंतजार करना चाहिए जब तक कि आपको इसे बाधित करने का कोई विशिष्ट कारण न हो .. – Jack

4

कहीं अस्थिर बूलियन stop बनाएं। तो कोड है कि सूत्र में चलाता है, नियमित रूप से

if (stop) // end gracefully by breaking out of loop or whatever 

कर धागा रोकने के लिए, true को stop निर्धारित किया है।

मुझे लगता है कि आपको इसे मैन्युअल रूप से करना होगा। आखिरकार, धागे में चलने वाले कोड में कोई विचार नहीं है कि क्या है और क्या सुंदर नहीं है।

+21

ध्यान दें कि आपको या तो लॉकिंग का उपयोग करने की आवश्यकता है या यह सुनिश्चित करने के लिए फ़ील्ड अस्थिर बनाना है कि रीडिंग थ्रेड लेखन थ्रेड से परिवर्तन देखता है। –

+0

@ जोन स्कीट: हाँ, यह बेहतर होगा। यद्यपि जिज्ञासा से बाहर, अगर क्षेत्र अस्थिर नहीं है तो कितनी देर तक रोक लग सकती है? –

+5

@ बार्ट: प्रैटिस में, शायद बिल्कुल लंबा नहीं। सिद्धांत में, हमेशा के लिए। –

10

आप अन्य एक से धागा मार नहीं करना चाहिए। इसे काफी बुरी आदत माना जाता है। हालांकि, कई तरीके हैं। आप थ्रेड की run विधि से return कथन का उपयोग कर सकते हैं। या आप जांच सकते हैं कि थ्रेड पहले से ही बाधित हो चुका है और फिर यह उसका काम रद्द कर देगा। उदा :

while (!isInterrupted()) { 
    // doStuff 
} 
+0

रन विधि शून्य है, यह कुछ भी वापस नहीं कर सकता है। –

+3

आप शून्य रिटर्न प्रकार के साथ खाली रिटर्न स्टेटमेंट का उपयोग कर सकते हैं, विधि – Xorty

+0

समाप्त हो जाएगी, यह पहले जवाब के समान है, सिवाय इसके कि आप केवल रन() विधि से बाहर निकलने की बजाय वापसी का उपयोग कर रहे हैं। और हाँ, आप केवल वापसी का उपयोग कर सकते हैं; और वह एक शून्य विधि से बाहर निकल जाएगा – Richard

3

आपको थ्रेड को स्टॉप-संदेश भेजने की आवश्यकता है और थ्रेड को संदेश प्राप्त होने पर स्वयं को कार्रवाई करने की आवश्यकता है। यह बहुत आसान है अगर लंबे समय से चल कार्रवाई पाश अंदर है:

public class StoppableThread extends Thread { 

    private volatile boolean stop = false; 

    public void stopGracefully() { 
    stop = true; 
    } 

    public void run() { 
    boolean finished = false; 
    while (!stop && !finished) { 
     // long running action - finished will be true once work is done 
    } 
    } 
} 
+1

जैसा कि जॉन स्कीट ने मेरे उत्तर पर टिप्पणी की, स्टॉप अस्थिर होना चाहिए –

+0

मैंने अपना जवाब संपादित किया लेकिन पता चल जाएगा और पता चल जाएगा, यह क्यों लागू होता है - आपके जवाब में, मैंने सोचा था, इसे अस्थिर होना चाहिए क्योंकि आपने इसका उल्लेख नहीं किया था विधि और ऐसा लगता है, 'स्टॉप' फ़ील्ड को सीधे एक्सेस किया जाना था। –

+1

मैंने पहले अस्थिर कीवर्ड के बारे में सोचा है और (मेरे अपने प्रश्न का विज्ञापन करने की कोशिश किए बिना :)), यहां कुछ जवाब दिए गए हैं: http://stackoverflow.com/questions/106591/do-you-ever- उपयोग-द-अस्थिर-कीवर्ड-इन-जावा – Richard

12

एक ध्वज का उपयोग कर अपने धागा को रोकने के लिए के बारे में बुरा हिस्सा है कि धागा इंतजार कर या तो सो रहा है, तो आप के लिए इसके लिए इंतजार करना पड़ता है प्रतीक्षा/सोना खत्म करो। यदि आप थ्रेड पर इंटरप्ट विधि को कॉल करते हैं तो इससे प्रतीक्षा या नींद कॉल को इंटरप्टेड एक्सेप्शन से बाहर किया जा सकता है।

कॉलिंग इंटरप्ट() एक बाधित संपत्ति भी सेट करता है जिसे आप ध्वज के रूप में उपयोग करने के लिए उपयोग कर सकते हैं यह जांचने के लिए कि क्या छोड़ना है (यदि थ्रेड इंतजार नहीं कर रहा है या सो रहा है)।

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

मैं एक कार्यकर्ता धागा है कि वेतन वृद्धि, जहां किसी कारण से बीच में एक नींद वहाँ में काम करता है लिखना चाहते कहो, और मैं नींद छोड़ने प्रसंस्करण बनाने के लिए नहीं करना चाहती है कि वेतन वृद्धि के लिए शेष काम कर रही बिना छोड़ दी , मैं सिर्फ यह छोड़ना चाहते अगर यह के बीच वेतन वृद्धि है:

class MyThread extends Thread 
{ 
    public void run() 
    { 
     while (!Thread.currentThread().isInterrupted()) 
     { 
      doFirstPartOfIncrement(); 
      try { 
       Thread.sleep(10000L); 
      } catch (InterruptedException e) { 
       // restore interrupt flag 
       Thread.currentThread().interrupt(); 
      } 
      doSecondPartOfIncrement(); 
     } 
    } 
} 

Here is an answer to a similar question, including example code.

1

एक धागा ही रोकने के लिए के लिए, कोई भी उल्लेख किया है लगता है (गलत) अपवाद का उपयोग कर:

abstract class SelfStoppingThread extends Thread { 

    @Override 
    public final void run() { 
     try { 
      doRun(); 
     } catch (final Stop stop) { 
      //optional logging 
     } 
    } 

    abstract void doRun(); 

    protected final void stopSelf() { 
     throw new Stop(); 
    } 

    private static final class Stop extends RuntimeException {}; 

} 

एक सबक्लास को सामान्य रूप से doRun() को ओवरराइड करने की आवश्यकता होती है जैसे आप थ्रेड के साथ करेंगे, और जब भी ऐसा लगता है कि यह रुकना चाहता है तो कॉल रोकें। आईएमओ थोड़ी देर में ध्वज का उपयोग करने से क्लीनर महसूस करता है।

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