Подтвердить что ты не робот

Android - лучший и безопасный способ остановить поток

Я хочу знать, какой лучший способ остановить поток в Android. Я знаю, что могу использовать AsyncTask вместо него и что есть метод cancel(). Я должен использовать Thread в моей ситуации. Вот как я использую Thread:

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

Итак, есть ли у кого-нибудь представление о том, что является лучшим способом остановить поток?

4b9b3361

Ответ 1

Вы должны сделать свои прерывания поддержки потоков. В принципе, вы можете вызвать yourThread.interrupt(), чтобы остановить поток, и в вашем методе run() вам нужно периодически проверять состояние Thread.interrupted()

Существует хороший учебник здесь.

Ответ 2

Эта ситуация ничем не отличается от стандартной Java. Вы можете использовать стандартный способ остановки потока:

class WorkerThread extends Thread {
    volatile boolean running = true;

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

Основная идея - время от времени проверять значение поля. Когда вам нужно остановить поток, вы установите для параметра running значение false. Кроме того, как отметил Крис, вы можете использовать механизм прерывания.

Кстати, когда вы используете AsyncTask, ваш apporach не будет сильно отличаться. Единственное различие заключается в том, что вам придется вызывать метод isCancel() из вашей задачи вместо специального поля. Если вы вызываете cancel(true), но не реализуете этот механизм, поток все равно не остановится сам по себе, он будет работать до конца.

Ответ 3

В Android действуют те же правила, что и в обычной среде Java. В Java нити не убиты, но остановка потока выполняется с помощью . Поток просят закончить, и поток может затем законно завершить работу.

Часто используется поле volatile boolean, которое поток периодически проверяет и завершает, когда оно установлено на соответствующее значение.

Я не использовал boolean, чтобы проверить, должен ли поток завершать. Если вы используете volatile в качестве модификатора поля, это будет работать надежно, но если ваш код становится более сложным, вместо использования других методов блокировки внутри цикла while может случиться так, что ваш код будет не заканчиваться вообще или по крайней мере занимает больше времени, как вам может захотеть.

Некоторые методы блокировки библиотеки поддерживают прерывание.

Каждый поток имеет уже булевский флаг прерванный статус, и вы должны его использовать. Он может быть реализован следующим образом:

public void run() {

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

}

public void cancel() { interrupt(); }

Исходный код, взятый из Java Concurrency на практике. Поскольку метод cancel() является общедоступным, вы можете позволить другому потоку вызывать этот метод, как вы хотели.

Существует также слабо названный статический метод interrupted, который очищает прерванный статус текущего потока.

Ответ 4

Метод Thread.stop(), который может использоваться для остановки потока, устарел; для получения дополнительной информации см. Почему Thread.stop, Thread.suspend и Thread.resume устарели?.

Лучше всего иметь переменную, с которой сам поток справляется, и добровольно выходит, если переменная равна определенному значению. Затем вы обрабатываете переменную внутри своего кода, когда хотите, чтобы поток вышел. Альтернативно, конечно, вы можете использовать AsyncTask.

Ответ 5

В настоящее время и, к сожалению, мы не можем ничего сделать, чтобы остановить поток....

Добавляя что-то к ответу Matt, мы можем вызвать interrupt(), но это не остановит поток... Просто говорит системе остановить поток, когда система хочет убить некоторые потоки. Отдых выполняется системой, и мы можем проверить его, вызвав interrupted().

[p.s.: Если вы действительно собираетесь с interrupt(), я попрошу вас сделать несколько экспериментов с коротким сном после вызова interrupt()]

Ответ 6

Дело в том, что вам нужно проверить, работает поток или нет !?

поле:

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;

Ответ 7

Для остановки потока существует 2 следующих способа.

  • Создайте изменчивую логическую переменную и измените ее значение на false и проверьте внутри потока.

    volatile isRunning = false;

    public void run() { if (! isRunning) {return;} }

  • Или вы можете использовать метод interrupt(), который можно получить внутри потока.

    SomeThread.interrupt();

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

Ответ 8

Я использовал этот метод.

Looper.myLooper().quit();

ты можешь попробовать.

Ответ 9

Это сработало для меня так. Введите статическую переменную в основной вид деятельности и регулярно проверяйте ее, как я делал ниже.

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;



       }
   }

}

Ответ 10

Если в вашем проекте есть класс потока с обработчиком, то, когда вы начали с одного из фрагмента класса, если вы хотите остановиться здесь, это решение, как остановить и избежать сбоя приложения, когда фрагмент удаляется из стека.

Этот код находится в Котлине. Это прекрасно работает.

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")



    }
}

Приведенный выше код останавливает работающий поток, когда вы переключаетесь на любой другой фрагмент или действие из текущего фрагмента. также он воссоздает при возврате к текущему фрагменту

Ответ 11

Попробуйте вот так

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

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

Ответ 12

Внутри любого класса Activity вы создаете метод, который назначает NULL экземпляру потока, который может использоваться как альтернатива методу амортизации stop() для остановки выполнения потока:

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;
    }
}
}

Это работает для меня без проблем.