Android - धागा बंद करने का सबसे अच्छा और सुरक्षित तरीका


79

मैं जानना चाहता हूं कि एंड्रॉइड में थ्रेड को रोकने का सबसे अच्छा तरीका कौन सा है। मुझे पता है कि मैं AsyncTaskइसके बजाय उपयोग कर सकता हूं और यह कि एक cancel()विधि है। मुझे Threadअपनी स्थिति में एस का उपयोग करना होगा । यहाँ मैं कैसे उपयोग कर रहा हूँ Thread:

Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //doing some work
        }
    };
new Thread(runnable).start();

तो, क्या किसी के पास कोई विचार है जो एक धागा को रोकने का सबसे अच्छा तरीका है?

जवाबों:


90

आपको अपने थ्रेड सपोर्ट को बाधित करना चाहिए। मूल रूप से, आप yourThread.interrupt()थ्रेड को रोकने के लिए कॉल कर सकते हैं और अपने रन () विधि में आपको समय-समय पर स्थिति की जांच करनी होगीThread.interrupted()

यहाँ एक अच्छा ट्यूटोरियल है


धन्यवाद, मैं हर समय रद्द () या स्टॉप () की तलाश में था।
मिलो ilernilovský

@ Milorecernilovský stop()विधि पदावनत है और आपको अब इसका उपयोग नहीं करना चाहिए।
Alston

29

यह स्थिति किसी भी तरह से मानक जावा से अलग नहीं है। आप किसी थ्रेड को रोकने के लिए मानक तरीके का उपयोग कर सकते हैं:

class WorkerThread extends Thread {
    volatile boolean running = true;

    public void run() {
        // Do work...
        if (!running) return;
        //Continue doing the work
    }
}

मुख्य विचार समय-समय पर क्षेत्र के मूल्य की जांच करना है। जब आपको अपने धागे को रोकने की आवश्यकता होती है, तो आप runningझूठे पर सेट होते हैं। इसके अलावा, जैसा कि क्रिस ने बताया है, आप रुकावट तंत्र का उपयोग कर सकते हैं।

वैसे, जब आप AsyncTask का उपयोग करते हैं, तो आपका एपोरच बहुत अलग नहीं होगा। अंतर केवल इतना है कि आपको isCancel()एक विशेष क्षेत्र होने के बजाय अपने कार्य से विधि को कॉल करना होगा । यदि आप कॉल करते हैं cancel(true), लेकिन इस तंत्र को लागू नहीं करते हैं, तो धागा अभी भी खुद को रोक नहीं पाएगा, यह अंत तक चलेगा।


23

Android पर सामान्य जावा वातावरण में समान नियम लागू होते हैं। जावा में थ्रेड्स मारे नहीं जाते हैं, लेकिन एक थ्रेड का ठहराव एक सहकारी तरीके से किया जाता है । थ्रेड को समाप्त करने के लिए कहा जाता है और थ्रेड फिर शालीनतापूर्वक बंद हो सकता है।

अक्सर एक volatile booleanफ़ील्ड का उपयोग किया जाता है जो थ्रेड समय-समय पर जांचता है और समाप्त होता है जब इसे संबंधित मान पर सेट किया जाता है।

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

कुछ अवरोधक पुस्तकालय विधियाँ रुकावट का समर्थन करती हैं।

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

public void run() {

   try {
      while(!Thread.currentThread().isInterrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }

}

public void cancel() { interrupt(); }

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

एक खराब नामित स्थैतिक विधि भी है interruptedजो वर्तमान थ्रेड की बाधित स्थिति को साफ करती है।


2
एंड्रॉइड स्टूडियो में यह कहते हैं, अपवाद 'java.lang.InterruptedException' को कभी भी संबंधित प्रयास ब्लॉक में नहीं फेंका जाता है?
क्रेपो

1
@ क्रोपो इसे लूप से पहले जोड़ें:if (Thread.interrupted()) { throw new InterruptedException();}
कोसो

16

Thread.stop()एक थ्रेड को रोकने के लिए जिस विधि का उपयोग किया जा सकता है, उसे हटा दिया गया है; अधिक जानकारी के लिए देखें; क्यों Thread.stop, Thread.suspend और Thread.resume डिप्रेस्ड हैं?

आपका सबसे अच्छा दांव एक वैरिएबल है जो थ्रेड खुद को कंसीव करता है, और स्वैच्छिक रूप से बाहर निकलता है यदि वैरिएबल एक निश्चित मान के बराबर होता है। जब आप थ्रेड से बाहर निकलना चाहते हैं तो आप अपने कोड के अंदर परिवर्तनशील हेरफेर करते हैं। वैकल्पिक रूप से, आप AsyncTaskइसके बजाय उपयोग कर सकते हैं ।


4
AsyncTask वास्तव में रुकावट तंत्र का एक विकल्प नहीं है, यह UI के साथ बातचीत करने के लिए अधिक साधन है। जैसा कि मैंने अपने उत्तर में बताया है, आपको अभी भी AsyncTask में उसी तंत्र को लागू करना होगा जैसे कि किसी भी सामान्य धागे में, यदि आप निष्पादन के दौरान इसे रोकना चाहते हैं।
मैल्कम

2

वर्तमान में और दुर्भाग्य से हम धागे को रोकने के लिए कुछ भी नहीं कर सकते हैं ...।

मैट के उत्तर में कुछ जोड़कर हम कॉल कर सकते हैं interrupt()लेकिन यह थ्रेड को रोकता नहीं है ... सिस्टम को थ्रेड को रोकने के लिए कहता है जब सिस्टम कुछ थ्रेड्स को मारना चाहता है। आराम सिस्टम द्वारा किया जाता है, और हम इसे कॉल करके जांच सकते हैं interrupted()

[पीएस: यदि आप वास्तव में interrupt()मेरे साथ जा रहे हैं तो मैं आपको कॉल करने के बाद एक छोटी नींद के साथ कुछ प्रयोग करने के लिए कहूंगा interrupt()]


2

इस तरह की कोशिश करो

Thread thread = new Thread() {
    @Override
    public void run() {
        Looper.prepare();   
        while(true){ 
            Log.d("Current Thread", "Running"); 
            try{
               Thread.sleep(1000);
            }catch(Exeption exception){ }
        }
    }
};

thread.start();
thread.interrupt();

1

एक धागा को रोकने के लिए 2 निम्नलिखित तरीके हैं।

  1. एक अस्थिर बूलियन वैरिएबल बनाएं और इसके मान को झूठे और धागे के अंदर जांचने के लिए बदलें।

    volatile isRunning = false;
    
    public void run() {
    if(!isRunning) {return;}       
    
    }
    
  2. या आप उस रुकावट () ​​विधि का उपयोग कर सकते हैं जो एक धागे के अंदर प्राप्त हो सकती है।

    SomeThread.interrupt();
    
    public void run() {
    if(Thread.currentThread.isInterrupted()) {return;}
     }
    


0

इसने मेरे लिए इस तरह काम किया। मुख्य गतिविधि में एक स्थिर चर का परिचय दें और नियमित रूप से इसकी जांच करें कि मैंने नीचे कैसे किया था।

public class MainActivity extends AppCompatActivity {


//This is the static variable introduced in main activity
public static boolean stopThread =false;



  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Thread thread = new Thread(new Thread1());
    thread.start();

    Button stp_thread= findViewById(R.id.button_stop);

    stp_thread.setOnClickListener(new Button.OnClickListener(){
           @Override
           public void onClick(View v){
              stopThread = true;
           }

     }

  }


  class Thread1 implements Runnable{

        public void run() {

        // YOU CAN DO IT ON BELOW WAY 
        while(!MainActivity.stopThread) {
             Do Something here
        }


        //OR YOU CAN CALL RETURN AFTER EVERY LINE LIKE BELOW

        process 1 goes here;

        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line



        process 2 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 3 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 4 goes here;



       }
   }

}

0

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

यह कोड कोटलिन में है । यह पूरी तरह से काम करता है।

class NewsFragment : Fragment() {

    private var mGetRSSFeedsThread: GetRSSFeedsThread? = null

    private val mHandler = object : Handler() {

        override fun handleMessage(msg: Message?) {


            if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                val updateXMLdata = msg.obj as String
                if (!updateXMLdata.isNullOrEmpty())
                    parseUpdatePager(CommonUtils.getJSONObjectFromXML(updateXMLdata).toString())

            } else if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                BaseActivity.make_toast(activity, resources.getString(R.string.pleaseTryAgain))
            }

        }
    }
    private var rootview: View? = null;
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        rootview = inflater?.inflate(R.layout.fragment_news, container, false);

        news_listView = rootview?.findViewById(R.id.news_listView)
        mGetRSSFeedsThread = GetRSSFeedsThread(this.activity, mHandler)


        if (CommonUtils.isInternetAvailable(activity)) {
            mGetRSSFeedsThread?.start()
        }


        return rootview
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true);

    }



    override fun onAttach(context: Context?) {
        super.onAttach(context)
        println("onAttach")
    }

    override fun onPause() {
        super.onPause()
        println("onPause fragment may return to active state again")

        Thread.interrupted()

    }

    override fun onStart() {
        super.onStart()
        println("onStart")

    }

    override fun onResume() {
        super.onResume()
        println("onResume fragment may return to active state again")

    }

    override fun onDetach() {
        super.onDetach()
        println("onDetach fragment never return to active state again")

    }

    override fun onDestroy() {
        super.onDestroy()

        println("onDestroy fragment never return to active state again")
       //check the state of the task
        if (mGetRSSFeedsThread != null && mGetRSSFeedsThread?.isAlive!!) {
            mGetRSSFeedsThread?.interrupt();
        } else {

        }

    }

    override fun onDestroyView() {
        super.onDestroyView()
        println("onDestroyView fragment may return to active state again")



    }

    override fun onStop() {
        super.onStop()
        println("onStop fragment may return to active state again")



    }
}

ऊपर का कोड चालू थ्रेड को रोकता है जब आप वर्तमान टुकड़े से किसी अन्य टुकड़े या गतिविधि पर स्विच करते हैं। जब आप वर्तमान खंड में वापस आते हैं तो यह भी पुन: बन जाता है


0

बात आपको यह जांचने की है कि धागा चल रहा है या नहीं !?

मैदान:

private boolean runningThread = false;

धागे में:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep((long) Math.floor(speed));
                        if (!runningThread) {
                            return;
                        }
                        yourWork();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

यदि आप थ्रेड को रोकना चाहते हैं, तो आपको नीचे फ़ील्ड बनाना चाहिए

private boolean runningThread = false;

2
यह बंद नहीं होगा Thread, यह केवल yourWork();कहा जा रहा से बंद हो जाएगा । इसका परीक्षण करने के लिए आप Logनीचे एक जोड़ सकते हैंpublic void run() {
KRK

@KRK मुझे यह पता है! और मैंने इस उत्तर को पोस्ट किया क्योंकि इसका बहुत उपयोगी है जब आप केवल कुछ को रोकना चाहते हैं और इसे फिर से शुरू करने के लिए थ्रेड के बिना कुछ भी नहीं करते हैं।
हादी नोट

@HadiNote KRK सही है। आप अपने उत्तर में बताएं If you want to stop the thread you should make the below field: private boolean runningThread = false;। यह सही नहीं है।
pookie

0

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

एंड्रॉइड डॉक्स के अनुसार, यह स्टॉप विधि के लिए प्रस्तावित प्रतिस्थापन होगा जिसे एपीआई 15 से हटा दिया गया है

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

मेरा धागा वर्ग

   class ThreadClass implements Runnable {
            ...
                  @Override
                        public void run() {
                            while (count < name.length()) {

                                if (!exited) // checks boolean  
                                  {
                                   // perform your task
                                                     }
            ...

OnStop और OnResume इस तरह दिखेगा

  @Override
    protected void onStop() {
        super.onStop();
        exited = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        exited = false;
    }

0

जैसा कि हम जानते हैं कि थ्रेड .stop () को JAVA में पदावनत किया जाता है, हुड के तहत थ्रेड .stop इसे रोकने के लिए थ्रेड पर रुकावट () ​​विधि को कॉल करता है, रुकावट का अर्थ उन विधियों से फेंका जाता है, जो थ्रेड का इंतजार करते रहते हैं निष्पादन पूरा होने के बाद सूचित करने के लिए कुछ अन्य सूत्र। रुकावट के कारण थ्रेड को कुछ भी नहीं होगा यदि इसे किसी थ्रेड के निष्पादन में संभाला नहीं जाता है, जैसे, if(Thread.interrupted())return; इसलिए, हम सभी को मूल रूप से थ्रेड की शुरुआत और स्टॉप को प्रबंधित करने की आवश्यकता है जैसे कि start()विधि को कॉल करना जैसे Thread.start()कि while(true)अंदर की run()विधि शुरू होती है । धागा और प्रत्येक पुनरावृत्ति में बाधित स्थिति के लिए जाँच करता है और धागे से लौटता है।

कृपया ध्यान दें कि एक धागा निम्नलिखित स्थितियों में नहीं मरेगा:

  1. धागा अभी तक रन () से वापस नहीं आया है।
  2. धागे के स्वामित्व वाली कोई भी वस्तु सुलभ है। (यह बाकी काम करने के लिए जीसी के संदर्भों को अशक्त / निष्क्रिय करने का संकेत देता है)

-2

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

public class MyActivity extends Activity {

private Thread mThread;  

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


        mThread =  new Thread(){
        @Override
        public void run(){
            // Perform thread commands...
    for (int i=0; i < 5000; i++)
    {
      // do something...
    }

    // Call the stopThread() method.
            stopThread(this);
          }
        };

    // Start the thread.
        mThread.start(); 
}

private synchronized void stopThread(Thread theThread)
{
    if (theThread != null)
    {
        theThread = null;
    }
}
}

यह मेरे लिए बिना किसी समस्या के काम करता है।


11
एक Threadचर सेट करना nullथ्रेड को रोकने के लिए कुछ भी नहीं कर सकता है। तर्क को nullअंदर तक सेट करना stopThreadसमय की पूरी बर्बादी है।
टेड हॉप

2
यह संभवतः धागे को कैसे रोक सकता है? इस पर सकारात्मक वोट क्यों हैं?
18

1
इससे धागा बंद नहीं होता है। थ्रेड अभी भी चल रहा है और यह थ्रेड के उदाहरण के लिए उस थ्रेड को नियंत्रित करना असंभव बना देता है, क्योंकि आपने इंस्टेंस खो दिया है (जो प्रक्रिया पूरी होने तक चालू रहेगा)
Teocci
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.