Приложение : платформа Android предоставляет множество помощников для одноразовой работы, фоновой работы и т. Д., Что может быть предпочтительнее, чем попытка прокрутить собственный поток во многих случаях. Как упомянуто в посте ниже, AsyncTask является хорошей отправной точкой для изучения. Я призываю читателей сначала ознакомиться с положениями фреймворка, прежде чем даже начать думать о создании собственных потоков.
В примере кода, который вы разместили, есть несколько проблем, которые я рассмотрю по порядку:
1) Thread.stop () уже довольно давно устарел, поскольку в некоторых случаях он может оставлять зависимые переменные в несовместимых состояниях. См. на этой странице ответов Sun для получения более подробной информации (Изменить: эта ссылка теперь неактивна, см. на этой странице, почему бы не использовать Thread.stop () ). Предпочтительный метод остановки и запуска потока следующий (при условии, что ваш поток будет работать неопределенно долго):
private volatile Thread runner;
public synchronized void startThread(){
if(runner == null){
runner = new Thread(this);
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
Thread moribund = runner;
runner = null;
moribund.interrupt();
}
}
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
}
}
Это всего лишь один пример того, как остановить поток, но вывод состоит в том, что вы несете ответственность за выход из потока так же, как и любой другой метод. Поддерживайте метод межпотокового взаимодействия (в этом случае переменную переменную, которая также может быть через мьютекс и т. Д.) И в логике вашего потока используйте этот метод связи, чтобы проверить, следует ли вам рано выйти, очистить и т. Д.
2) Ваш список измерений доступен одновременно нескольким потокам (потоку событий и вашему пользовательскому потоку) без какой-либо синхронизации. Похоже, вам не нужно накатывать собственную синхронизацию, вы можете использовать BlockingQueue .
3) Вы создаете новый сокет каждую итерацию отправляющего потока. Это довольно тяжелая операция, и она действительно имеет смысл, если вы ожидаете, что измерения будут происходить крайне редко (скажем, один час или меньше). Либо вам нужен постоянный сокет, который не воссоздается в каждом цикле потока, либо вы хотите запустить один выстрел, который вы можете «запустить и забыть», который создает сокет, отправляет все соответствующие данные и завершает работу. (Краткое примечание об использовании постоянного сокета, методы сокетов, блокирование которых, например чтение, не может быть прервано Thread.interrupt (), и поэтому, когда вы хотите остановить поток, вы должны закрыть сокет, а также вызвать прерывание)
4) Нет смысла бросать ваши собственные исключения из потока, если вы не собираетесь перехватывать его где-то еще. Лучшее решение - записать ошибку и, если она неисправима, остановить поток. Поток может остановить себя с помощью кода, подобного (в том же контексте, что и выше):
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
if(/*fatal error*/){
stopThread();
return; //optional in this case since the loop will exit anyways
}
}
}
Наконец, если вы хотите быть уверенным, что поток завершает работу с остальной частью вашего приложения, несмотря ни на что, хорошим методом является вызов Thread.setDaemon (true) после создания и перед запуском потока. Это помечает поток как поток демона, что означает, что виртуальная машина будет гарантировать его автоматическое уничтожение, если не запущены потоки, не являющиеся демонами (например, если ваше приложение закрывается).
Соблюдение передовых методов работы с потоками должно гарантировать, что ваше приложение не зависает и не замедляет работу телефона, хотя они могут быть довольно сложными:)