Я хочу знать, как лучше всего остановить поток в Android. Я знаю, что могу использовать AsyncTask
вместо него и что есть cancel()
метод. Я должен использовать Thread
s в моей ситуации. Вот как я использую Thread
:
Runnable runnable = new Runnable() {
@Override
public void run() {
//doing some work
}
};
new Thread(runnable).start();
Итак, кто-нибудь знает, как лучше всего остановить поток?
android
thread-safety
Android-дроид
источник
источник
stop()
Метод @ MilošČernilovský устарел, и вы больше не должны его использовать.Эта ситуация ничем не отличается от стандартной Java. Вы можете использовать стандартный способ остановить поток:
class WorkerThread extends Thread { volatile boolean running = true; public void run() { // Do work... if (!running) return; //Continue doing the work } }
Основная идея - время от времени проверять значение поля. Когда вам нужно остановить поток, вы устанавливаете
running
значение false. Кроме того, как указал Крис, вы можете использовать механизм прерывания.Кстати, когда вы используете AsyncTask, ваш аппорач не будет сильно отличаться. Единственное отличие состоит в том, что вам придется вызывать
isCancel()
метод из вашей задачи вместо того, чтобы иметь специальное поле. Если вы вызоветеcancel(true)
, но не реализуете этот механизм, поток все равно не остановится сам по себе, он будет работать до конца.источник
На Android действуют те же правила, что и в обычной среде Java. В Java потоки не уничтожаются, но остановка потока выполняется совместно . Требуется завершить поток, после чего он может корректно завершить работу.
Часто используется
volatile boolean
поле, которое поток периодически проверяет и завершает работу, когда для него установлено соответствующее значение.Я бы не стал использовать a,
boolean
чтобы проверять, следует ли завершать поток . Если вы используетеvolatile
в качестве модификатора поля, это будет работать надежно, но если ваш код станет более сложным, поскольку вместо этого используются другие методы блокировки внутриwhile
цикла, может случиться так, что ваш код вообще не завершится или, по крайней мере, займет больше времени, чем вы может захотеть.Каждый поток уже имеет состояние прерывания логического флага, и вы должны его использовать. Реализовать это можно так:
public void run() { try { while(!Thread.currentThread().isInterrupted()) { // ... } } catch (InterruptedException consumed) /* Allow thread to exit */ } } public void cancel() { interrupt(); }
Исходный код взят из Java Concurrency in Practice . Поскольку
cancel()
метод является общедоступным, вы можете позволить другому потоку вызывать этот метод по своему усмотрению.Существует также статический метод с плохим именем,
interrupted
который очищает прерванный статус текущего потока.источник
if (Thread.interrupted()) { throw new InterruptedException();}
Thread.stop()
Метод , который может быть использован , чтобы остановить поток устарел; для получения дополнительной информации см; Почему Thread.stop, Thread.suspend и Thread.resume устарели? .Лучше всего иметь переменную, с которой сам поток обращается к нему и добровольно завершает работу, если переменная равна определенному значению. Затем вы манипулируете переменной внутри своего кода, когда хотите, чтобы поток завершился. В качестве альтернативы, конечно, вы можете использовать
AsyncTask
вместо.источник
В настоящее время, к сожалению, мы не можем ничего сделать, чтобы остановить обсуждение ....
Добавляя что-то к ответу Мэтта, мы можем вызвать,
interrupt()
но это не останавливает поток ... Просто говорит системе остановить поток, когда система хочет убить некоторые потоки. Остальное делает система, и мы можем проверить это, позвонивinterrupted()
.[ps: Если вы действительно согласны,
interrupt()
я бы попросил вас поэкспериментировать с коротким сном после звонкаinterrupt()
]источник
Попробуйте как это
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();
источник
Есть два предпочтительных способа остановить поток.
Создайте изменчивую логическую переменную, измените ее значение на false и проверьте внутри потока.
volatile isRunning = false; public void run() { if(!isRunning) {return;} }
Или вы можете использовать метод interrupt (), который можно получить внутри потока.
SomeThread.interrupt(); public void run() { if(Thread.currentThread.isInterrupted()) {return;} }
источник
Я использовал этот метод.
Looper.myLooper().quit();
ты можешь попробовать.
источник
У меня это сработало вот так. Внесите статическую переменную в основное действие и регулярно проверяйте ее, как я это сделал, как показано ниже.
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; } } }
источник
Если в вашем проекте есть класс потока с обработчиком, когда вы начали с одного из классов фрагментов, если вы хотели остановиться, вот решение, как остановить и избежать сбоя приложения при удалении фрагмента из стека.
Этот код находится в Котлине . Он отлично работает.
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") } }
Приведенный выше код останавливает запущенный поток, когда вы переключаетесь на любой другой фрагмент или действие из текущего фрагмента. также он воссоздается, когда вы возвращаетесь к текущему фрагменту
источник
Дело в том, что нужно проверить, запущен поток или нет !?
Поле:
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;
источник
Thread
, а только перестанетyourWork();
вызываться. Чтобы проверить это, вы можете добавитьLog
нижеpublic void run() {
If you want to stop the thread you should make the below field: private boolean runningThread = false;
. Это не так.Мое требование немного отличалось от вопроса, но это также полезный способ остановить поток для выполнения своих задач. Все, что я хотел сделать, это остановить поток при выходе из экрана и возобновить его при возврате на экран.
Согласно документации Android, это будет предложенная замена для метода остановки, который устарел из API 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; }
источник
Поскольку мы знаем, что Thread.stop () устарел в JAVA, под капотом Thread.stop вызывает метод interrupt () в потоке, чтобы остановить его, прерывание должно вызываться из методов, которые заставляют поток ждать какой-то другой поток для уведомления после завершения выполнения. Прерывание ничего не вызовет для потока, если оно не будет обработано при выполнении потока, например,
if(Thread.interrupted())return;
Итак, в целом нам нужно в основном управлять запуском и остановкой потока, например, вызовstart()
метода, например,Thread.start()
запускаетwhile(true)
внутриrun()
метода поток и проверяет состояние прерывания на каждой итерации и возвращается из потока.Обратите внимание, что поток не умирает в следующих ситуациях:
источник
Внутри любого класса 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; } } }
У меня это работает без проблем.
источник
Thread
переменной в значение неnull
приведет к остановке потока. Ставить аргументnull
внутрьstopThread
- пустая трата времени.