Intereting Posts
Сделайте линейную компоновку, выбранную как элемент списка в виде списка (Android) Реферат: сделайте снимок с использованием намерения камеры и отобразите фотографию с правильной ориентацией (работает, надеюсь, на все устройства) Кратко сокрытие ActionBar без изменения размера Как уменьшить внутреннюю прописку вокруг текста в объекте кнопки Android? Приложение Android не совместимо с устройствами, которые загружают Google Play Отправка данных обратно в главную активность в android Разрешение Android READ_EXTERNAL_STORAGE не работает Могу ли я использовать onScrollListener для ScrollView? Девять-патч против векторной графики Можно ли программно отключить тихий режим в андроиде? Android-новичок – Поместите изображение в DragEvent Binding Library Mono для Android Не удалось найти com.google.android.gms: play-services: 3.1.59 3.2.25 4.0.30 4.1.32 4.2.40 4.2.42 4.3.23 4.4.52 5.0.77 5.0.89 5.2.08 6.1. 11 6.1.71 6.5.87 Android, Расширяемое представление списка не реагирует на щелчок !!! Он не расширяется Программный пакет линейного макета Android

Остановка / уничтожение нити

У меня есть Служба, которая запускает Thread и Runnable.

t = new Thread(new Runnable() { public void run() { doSomething(); } }); t.start(); 

Причиной потока является выполнение задачи Async doSomething () . Пока давайте не будем беспокоиться о другом классе AsyncTask. Я пробовал это, и это не работает для моего дела. Изменить: я не могу использовать AsyncTask, потому что он предназначен только для потока пользовательского интерфейса. Этот кусок кода должен работать внутри Сервиса, поэтому нет, нет AsyncTask 🙁

DoSomething () содержит некоторые внешние библиотеки, поэтому проблема, с которой я сталкиваюсь, заключается в том, что ее можно потенциально повесить на одну из команд, без возврата какого-либо значения (следовательно, проверка ошибок даже не может быть выполнена)

Чтобы обойти это, я захочу, в какой-то момент, уничтожить Службу.

 stopService(new Intent("net.MyService.intent)); 

Это прекрасно работает и легко проверяется по телефону. Тем не менее, Thread, который был создан выше, будет продолжать работать даже тогда, когда Служба, которая породила его, будет уничтожена.

Поэтому я ищу правильные команды для вставки в onDestroy () службы, которые очистят Thread для меня.

 t.destroy(); t.stop(); 

Обе амортизируются и вызывают сбои приложений.

Я взял этот код откуда-то

 @Override public void onDestroy() { Thread th = t; t = null; th.interrupt(); super.onDestroy(); } 

Но он все еще не работает, поток продолжает работать. Любая помощь ребята?

Solutions Collecting From Web of "Остановка / уничтожение нити"

Способы destroy и stop потока по своей сути являются тупиковыми и небезопасными. Их существование также дает иллюзию, что может быть какой-то способ немедленно остановить другой поток, когда что-то еще говорит об этом.

Я понимаю ваше мышление, с вашей точки зрения, это один основной поток, и когда этот поток не получил ответа от рабочего потока, вы хотели бы его убить и перезапустить, не заботясь о том, что это такое , Но причина, по которой эти методы устарели, – это то, что вам нужно . Много.

Что делать, если поток имеет блокировку вокруг переменной, которую нужно использовать позже? Что делать, если поток имеет дескриптор файла? Во всех этих случаях и многом другом просто прекращение потока при его текущей работе оставит все в беспорядке – скорее всего, ваше приложение просто прорвется дальше по линии.

Поэтому для того, чтобы поток был прерываемым или отменяемым или остановленным, он должен сам управлять этим потоком. Если нить или операция не дают возможности прервать себя, тогда вы не можете ее прервать – предполагается, что это будет небезопасно.

Если вы управляете буквально

 public void run() { doSomething(); } 

То нет возможности прервать его. Можно было бы надеяться, что если doSomething была долгой операцией, возможно, существует способ взаимодействовать с ней поэтапно с чем-то вроде

 public void run() { while (running) { MyParser.parseNext(); } } 

Или иметь возможность передавать переменную по ссылке, которая указывает, прерывается ли поток или нет, и, надеюсь, метод будет прервать себя в подходящем месте.

Помните, что операция блокировки блокируется. Невозможно обойти это, вы не можете отменить его частично.

Вы проверили документацию о примитивной декларации Java, которая упоминается в JavaDoc API нитей. Вы найдете подсказки для решения своей проблемы.

Почему вы не используете AsyncTask ?

Задача может быть отменена в любое время путем вызова cancel (boolean). Вызов этого метода приведет к последующим вызовам isCancelled (), чтобы вернуть true. После вызова этого метода onCancelled (Object) вместо onPostExecute (Object) будет вызываться после того, как doInBackground (Object []) вернется. Чтобы гарантировать, что задача будет отменена как можно быстрее, вы всегда должны проверять возвращаемое значение isCancelled () периодически из doInBackground (Object []), если это возможно (например, внутри цикла).

Альтернативный ответ

Используйте следующий код:

 MyThread thread; // class field 

Создайте и запустите поток, как вы делаете это прямо сейчас.

 thread = new MyThread(); thread.start(); 

Когда служба уничтожается, «сигнализируйте» нить для выхода

 public void onDestroy() { // Stop the thread thread.abort = true; thread.interrupt(); } 

Вот реализация потока

 //another class or maybe an inner class class MyThread extends Thread { syncronized boolean abort = false; //ugly, I know public void run() { try { if(!abort) doA(); if(!abort) doB(); if(!abort) doC(); if(!abort) doD(); } catch (InterruptedException ex) { Log.w("tag", "Interrupted!"); } } } 

Вы можете прочитать следующее:

  • Как вы убиваете поток в Java?
  • Thread Primitive Устаревание, как уже указывал Классен
  • http://www.devx.com/tips/Tip/31728 – основал мой код здесь, но есть некоторые проблемы с кодом!

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

ОБНОВИТЬ

Я видел этот образец в codeguru :

 public class Worker implements Runnable { private String result; public run() { result = blockingMethodCall(); } public String getResult() { return result; } } public class MainProgram { public void mainMethod() { ... Worker worker = new Worker(); Thread thread = new Thread(worker); thread.start(); // Returns when finished executing, or after maximum TIME_OUT time thread.join(TIME_OUT); if (thread.isAlive()) { // If the thread is still alive, it's still blocking on the methodcall, try stopping it thread.interrupt(); return null; } else { // The thread is finished, get the result return worker.getResult(); } } } 

Мне нравится использовать следующий подход:

 class MyHandler extends Handler { final Semaphore stopEvent = new Semaphore(0); @Override public void handleMessage(Message msg) { try { while (!stopEvent.tryAcquire(0, TimeUnit.SECONDS)) { doSomething(); if (stopEvent.tryAcquire(SLEEP_TIME, TimeUnit.MILLISECONDS)) { break; } } } catch (InterruptedException ignored) { } stopSelf(); } } 

На сервисе onDestroy просто отпустите stopEvent:

 @Override public void onDestroy() { myHandler.stopEvent.release(); myHandler = null; super.onDestroy(); } 

Лучше использовать глобальную переменную stopThread, остановите поток, когда переменная изменена на true.

 btnStop.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0){ stopThread = true; } }); public void run() { while (!stopThread) { //do something } } 

Я думаю, что лучший способ создать и установить связь с другим потоком – использовать AsyncTask . Вот пример одного:

 public class Task extends AsyncTask<Void, Void, Void> { private static final String TAG = "Task"; private boolean mPaused; private Runnable mRunnable; public Task(Runnable runnable) { mRunnable = runnable; play(); } @Override protected Void doInBackground(Void... params) { while (!isCancelled()) { if (!mPaused) { mRunnable.run(); sleep(); } } return null; } private void sleep() { try { Thread.sleep(10); } catch (InterruptedException e) { Log.w(TAG, e.getMessage()); } } public void play() { mPaused = false; } public void pause() { mPaused = true; } public void stop() { pause(); cancel(true); } public boolean isPaused() { return mPaused; } } 

Теперь вы можете легко использовать этот класс и начать поток, написав:

 Task task = new Task(myRunnable); task.execute((Void) null); 

Наряду с этим вы можете легко приостановить или остановить поток из цикла:

Пример приостановки и воспроизведения темы:

 mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (task.isPaused()) { task.play(); } else { task.pause(); } } }); 

Пример остановки и запуска потока:

 mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (task.isCancelled()) { task = new Task(myRunnable); task.execute((Void) null); } else { task.stop(); } } });