- Потоки
- Использование фоновых потоков
- Плохое приложение
- Запуск потока
- Усыпить поток
- Приоритет потоков
- Отмена выполнения потока
- Как остановить выполнение Через определенное время в Java
- 1. Обзор
- 2. Использование петли
- 3. Использование механизма прерывания
- 3.1. Использование таймера
- 3.2. Использование метода Future#get
- 3.3. Использование Услуги Планового Исполнителя
- 4. Есть ли гарантия?
- 5. Заключение
- Как принудительно закрыть приложение или игру на Android которая зависла
- Как принудительно закрыть приложения и игры на смартфоне Android: распространенные способы
- Способ первый: При помощи функции последние приложения
- Как принудительно остановить работу приложений – пошаговая инструкция
Потоки
Потоки позволяют выполнять несколько задач одновременно, не мешая друг другу, что даёт возможность эффективно использовать системные ресурсы. Потоки используются в тех случаях, когда одно долгоиграющее действие не должно мешать другим действиям. Например, у нас есть музыкальный проигрыватель с кнопками воспроизведения и паузы. Если вы нажимаете кнопку воспроизведения и у вас запускается музыкальный файл в отдельном потоке, то вы не можете нажать на кнопку паузы, пока файл не воспроизведётся полностью. С помощью потоков вы можете обойти данное ограничение.
Использование фоновых потоков
Чтобы быть уверенным, что ваше приложение не теряет отзывчивости, хорошим решением станет перемещение всех медленных, трудоёмких операций из главного потока приложения в дочерний.
Применение фоновых потоков — необходимое условие, если вы хотите избежать появления диалогового окна для принудительного закрытия приложения. Когда активность в Android на протяжении 5 секунд не отвечает на события пользовательского ввода (например, нажатие кнопки) или приёмник широковещательных намерений не завершает работу обработчика onReceive() в течение 10 секунд, считается, что приложение зависло. Подобные ситуации следует избегать любой ценой. Используйте фоновые потоки для всех трудоёмких операций, включая работу с файлами, сетевые запросы, транзакции в базах данных и сложные вычисления.
Android предоставляет несколько механизмов перемещения функциональности в фоновый режим.
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
- Handlers
- AsyncTask
Класс AsyncTask позволяет определить операции, которые будут выполняться в фоне, вы также будете иметь доступ к обработчику событий, что позволит отслеживать прогресс выполнения задач и выводить результаты в контексте главного графического потока. Подробнее об этом классе в отдельной статье.
Хотя использование AsyncTask — хорошее решение, случается, что для работы в фоновом режиме приходится создавать собственные потоки и управлять ими.
В Java есть стандартный класс Thread, который вы можете использовать следующим образом:
Данный способ подходит только для операций, связанных с временем. Но вы не сможете обновлять графический интерфейс программы.
Если вам нужно обновлять интерфейс программы, то нужно использовать AsyncTask, о котором говорилось выше, или вы можете реализовать ваш собственный класс, наследованный от Thread, используя объект Handler из пакета android.os для синхронизации с потоком GUI перед обновлением пользовательского интерфейса.
Вы можете создавать дочерние потоки и управлять ими с помощью класса Handler, а также классов, доступных в пространстве имён java.lang.Thread. Ниже показан простой каркас для переноса операций в дочерний поток.
Плохое приложение
Напишем «плохое» приложение, неправильно использующее основной поток. Однажды мы писали программу для подсчёта ворон. На этот раз будем считать чёрных котов, которые перебегают нам дорогу. Зачем они это делают — молчит наука. Может быть собранная статистика поможет разгадать тайну. Добавим на экран активности кнопки и текстовую метку. Код для щелчка кнопки.
Для имитации тяжёлой работы программа делает паузу на двадцать секунд, а потом выводит текст с подсчётом котов. Если нажать на кнопку один раз и подождать двадцать секунд, то программа отработает как положено. Но представьте себе, что вы нажали на кнопку один раз. Программа запустила паузу. Вы, не дожидаясь окончания паузы, снова нажали на кнопку. Программа должна выполнить вашу команду, но предыдущая команда ещё не отработала и наступает конфликт. Попробуйте нажать на кнопку несколько раз с небольшими перерывами. В какой-то момент приложение зависнет и выведет системное диалоговое окно:
В реальных приложениях такое окно может разозлить пользователя и он поставит низкую оценку вашему приложению.
В данном случае ошибку вызывает не сам вывод текста в текстовой метке, который, к слову, тоже выполняется в основном потоке, а сам щелчок кнопки. Если вы закомментируете последние две строчки кода, связанные с TextView, то ошибка сохранится.
Вам необходимо перенести трудоёмкую задачу в отдельный поток. Для этого создаётся экземпляр класса Runnable, у которого есть метод run(). Далее создаётся объект Thread, в конструкторе у которого указывается созданный Runnable. После этого можно запускать новый поток с помощью метода start(). Перепишем пример.
Весь код мы перенесли в метод run(). Теперь вы можете безостановочно щёлкать по кнопке. На этот раз приложение сохранит свою работоспособность. Чтобы в этом убедиться, в код добавлено протоколирование логов Log.i(). При каждом нажатии создаётся новый поток, в котором выполняется код. Потоки друг другу не мешают и дожидаются своей очереди, когда система позволит им отработать.
Основной поток также называют UI-потоком. Имено в главном потоке можно обновить текст у текстовой метки. В создаваемых нами потоках это делать нельзя. Если вы уберёте комментарии с последнего примера и запустите проект, то получите сообщение об ошибке.
Нужен некий посредник между создаваемыми потоками и основным UI-потоком. В роли такого посредника служит класс Handler (полное название класса android.os.Handler, не перепутайте). Вам нужно создать экземпляр класса и указать код, который нужно выполнить.
После строчки кода с Log.i() добавьте вызов метода посредника.
Поток вызывает посредника, который в свою очередь обновляет интерфейс. В нашем случае посредник посылает пустое сообщение от потока.
Но бывает так, что от потока требуется получить информацию для обработки. Ниже упрощённый пример.
Запуск потока
Предположим, мы разрабатываем собственный проигрыватель. У нас есть кнопка Play, которая вызывает метод play() для воспроизведения музыки:
Теперь запустим метод в другом потоке. Сначала создаётся новый поток. Далее описывается объект Runnable в конструкторе потока. А внутри созданного потока вызываем наш метод play(). И, наконец, запускаем поток.
Усыпить поток
Иногда требуется временно приостановить поток («усыпить»):
Приоритет потоков
Для установки приоритета процесса используется метод setPriority(), который вызывается до запуска потока. Значение приоритета может варьироваться от Thread.MIN_PRIORITY (1) до Thread.MAX_PRIORITY (10):
Отмена выполнения потока
У потока есть метод stop(), но использовать его не рекомендуется, поскольку он оставляет приложение в неопределённом состоянии. Обычно используют такой подход:
Существует и другой способ, когда все запускаемые потоки объявляются демонами. В этом случае все запущенные потоки будут автоматически завершены при завершении основного потока приложения:
Источник
Как остановить выполнение Через определенное время в Java
Изучите различные способы завершения длительного выполнения через определенное время в Java
Автор: baeldung
Дата записи
1. Обзор
В этой статье мы узнаем, как можно завершить длительное выполнение через определенное время. Мы рассмотрим различные варианты решения этой проблемы. Кроме того, мы рассмотрим некоторые из их ловушек.
2. Использование петли
Представьте себе, что мы обрабатываем кучу элементов в цикле, например, некоторые детали элементов продукта в приложении электронной коммерции, но, возможно, нет необходимости заполнять все элементы.
На самом деле мы хотели бы обрабатывать только до определенного времени, а после этого мы хотим остановить выполнение и показать все, что список обработал до этого времени.
Давайте рассмотрим краткий пример:
Здесь петля разорвется, если время превысит предел в 30 секунд. В приведенном выше решении есть несколько примечательных моментов:
- Низкая точность: Цикл может работать дольше, чем установленный лимит времени . Это будет зависеть от времени, которое может занять каждая итерация. Например, если каждая итерация может занять до 7 секунд, то общее время может увеличиться до 35 секунд, что примерно на 17% больше, чем желаемый лимит времени в 30 секунд
- Блокировка: Такая обработка в основном потоке может быть не очень хорошей идеей, так как она будет блокировать его в течение длительного времени . Вместо этого эти операции должны быть отделены от основного потока
В следующем разделе мы обсудим, как подход, основанный на прерываниях, устраняет эти ограничения.
3. Использование механизма прерывания
Здесь мы будем использовать отдельный поток для выполнения длительных операций. Основной поток будет посылать сигнал прерывания рабочему потоку по таймауту.
Если рабочий поток все еще жив, он поймает сигнал и остановит его выполнение. Если рабочий завершит работу до истечения тайм-аута, это никак не повлияет на рабочий поток.
Давайте взглянем на рабочий поток:
Здесь Thread.sleep имитирует длительную операцию. Вместо этого может быть любая другая операция. Важно проверить флаг прерывания, потому что не все операции прерываются . Поэтому в этих случаях мы должны вручную проверить флаг.
Кроме того, мы должны проверять этот флаг на каждой итерации, чтобы убедиться, что поток прекращает выполнение самого себя в течение задержки не более одной итерации.
Далее мы рассмотрим три различных механизма передачи сигнала прерывания.
3.1. Использование таймера
Кроме того, мы можем создать TimerTask для прерывания рабочего потока по таймауту:
Здесь мы определили a TimerTask , который принимает рабочий поток в момент его создания. Он прерывает рабочий поток при вызове его run метода . Timer вызовет TimerTask после указанной задержки:
3.2. Использование метода Future#get
Мы также можем использовать метод get a Future вместо использования a Таймер :
Здесь мы использовали ExecutorService для отправки рабочего потока, который возвращает экземпляр Future , чей метод get заблокирует основной поток до указанного времени. Это поднимет TimeoutException после указанного таймаута. В блоке catch мы прерываем рабочий поток, вызывая метод cancel для объекта F uture .
Основное преимущество этого подхода по сравнению с предыдущим заключается в том, что он использует пул для управления потоком, в то время как Таймер использует только один поток (без пула) .
3.3. Использование Услуги Планового Исполнителя
Мы также можем использовать ScheduledExecutorService для прерывания задачи. Этот класс является расширением ExecutorService и предоставляет ту же функциональность с добавлением нескольких методов, которые имеют дело с планированием выполнения. Это может выполнить заданную задачу после определенной задержки в заданные единицы времени:
Здесь мы создали запланированный пул потоков размера два с помощью метода newScheduledThreadPool . Метод ScheduledExecutorService# schedule принимает Runnable , значение задержки и единицу задержки.
Приведенная выше программа планирует выполнение задачи через одну секунду с момента подачи. Эта задача отменит исходную длительную задачу.
Обратите внимание, что в отличие от предыдущего подхода, мы не блокируем основной поток, вызывая метод Future#get . Поэтому это наиболее предпочтительный подход среди всех вышеперечисленных подходов .
4. Есть ли гарантия?
Нет никакой гарантии, что выполнение будет остановлено через определенное время . Основная причина заключается в том, что не все методы блокировки прерываемы. На самом деле существует лишь несколько четко определенных методов, которые можно прервать. Таким образом, если поток прерывается и установлен флаг, ничего больше не произойдет, пока он не достигнет одного из этих прерываемых методов .
Например, методы read и write прерываются только в том случае, если они вызываются в потоках, созданных с помощью InterruptibleChannel . BufferedReader не является InterruptibleChannel . Таким образом, если поток использует его для чтения файла, вызов interrupt() в этом потоке, заблокированном в методе read , не имеет никакого эффекта.
Однако мы можем явно проверять наличие флага прерывания после каждого чтения в цикле. Это даст разумную гарантию остановить поток с некоторой задержкой. Но это не гарантирует остановку потока после строгого времени, потому что мы не знаем, сколько времени может занять операция чтения.
С другой стороны, метод wait класса Object прерываем. Таким образом, поток, заблокированный в методе wait , немедленно выдаст исключение InterruptedException после установки флага прерывания.
Мы можем идентифицировать методы блокировки, ища throws | InterruptedException в их сигнатурах методов.
Один важный совет заключается в том, чтобы избегать использования устаревшего метода Thread.stop () . Остановка потока приводит к тому, что он разблокирует все мониторы, которые он заблокировал. Это происходит из-за исключения Thread Death , которое распространяется вверх по стеку.
Если какой-либо из объектов, ранее защищенных этими мониторами, находился в несогласованном состоянии, несогласованные объекты становятся видимыми для других потоков. Это может привести к произвольному поведению, которое очень трудно обнаружить и объяснить.
5. Заключение
В этом уроке мы изучили различные методы остановки выполнения через определенное время, а также плюсы и минусы каждого из них. Полный исходный код можно найти на GitHub .
Источник
Как принудительно закрыть приложение или игру на Android которая зависла
Для тех, кто впервые начинает пользоваться Android устройством непонятно, а как же закрывать запущенные приложения. Ведь в отличие от ОС Windows, к которой все привыкли, здесь нет непосредственно на экране смартфона (планшета) окна работающей программы с кнопкой для ее закрытия как в Windows.
В этом материале для начинающих пользователей мы расскажем, как закрыть приложение на Андроид.
Как принудительно закрыть приложения и игры на смартфоне Android: распространенные способы
Андроид едва ли не с первых дней существования получил многозадачность. А если несколько программ могут работать одновременно, то у пользователя должна иметься возможность какие-то из них закрывать. Или даже отключать, но об этом мы поговорим чуть ниже. Закрытие приложения подразумевает собой его выгрузку из оперативной памяти, заодно программа перестанет нагружать процессор
Далее я расскажу вам о всех способах которые помогут закрыть вам приложения работающие в фоновом режиме вашего Android устройства.
Способ первый: При помощи функции последние приложения
Если вы ищете самый быстрый способ закрыть приложения на вашем устройстве, используйте меню последних приложений.
Обратите внимание, что очистка приложений через это меню не приведет к уничтожению сервисов, предоставляемых приложением, то есть вы все равно будете получать уведомления и лайки.
- Запустите меню последних приложений. В зависимости от вашего устройства, есть разные способы доступа к этому меню. Некоторым из вас нужно слегка провести пальцем вверх от нижней части главного экрана, коснуться квадратного значка в нижней части экрана или выбрать нужную кнопку на телефоне.
- Найдите приложение, которое хотите закрыть. Проведите пальцем вверх или вниз (влево или вправо на некоторых устройствах), чтобы найти приложение, которое вы хотите закрыть.
- Нажмите, удерживайте и проведите пальцем, чтобы закрыть приложение. Если ваши приложения находятся в горизонтальном списке, вам нужно провести вверх, чтобы сделать это. Но если ваши приложения находятся в вертикальной ориентации, проведите пальцем влево или вправо, чтобы закрыть приложение.
- Если вы хотите закрыть все запущенные приложения, есть функция «ЗАКРЫТЬ ВСЕ» или «ОЧИСТИТЬ ВСЕ», чтобы вам не приходилось закрывать все из них вручную
Как принудительно остановить работу приложений – пошаговая инструкция
Использование функции Force Stop на вашем устройстве также закрывает фоновые процессы и службы приложения. Так что, если ваше приложение всегда дает сбой или у вас возникают похожие проблемы, принудительно остановите свое приложение и затем очистите кэш.
Для того, чтобы это сделать воспользуйтесь следующей инструкцией:
- Перейдите в меню приложений. Перейдите к настройкам в панели уведомлений или в панели приложений. Прокрутите вниз и нажмите на приложения.
- Выберите приложение, которое вы хотите закрыть. Измените меню и покажите все приложения на вашем устройстве. Оттуда найдите приложение, которое вызывает проблемы, и выберите его.
- Выберите Force Stop. На странице приложения, на которой вы находитесь, найдите кнопку «Force Stop» и выберите кнопку. Если вы решили, что приложение вам не нужно, вы также можете удалить его оттуда.
- Подтвердите. Как только вы убьете работающее приложение, оно не перезапустит и не запустит свои процессы, если вы не запустите приложение самостоятельно. Таким образом, приложение не будет продолжать вас беспокоить, даже если вы не удалили его.
Источник