Потоки (Threads)

Отрисовка различных View происходит в главном потоке. И если в главном потоке выполнять загрузку больших файлов (или выполнять различные длительные операции), то приложение будет зависать. А это не очень хорошо. Поэтому длительные (или высоконагруженные) операции нужно выполнять в другом потоке.

1. Thread, Runnable, Handler

Изменения пользовательского интерфейса(UI) могут происходить только в главном потоке. Для этого можно использовать метод Activity.runOnUiThread().

Так же можно использовать класс Handler.

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

ThreadDownloader.java:

И перепишем наш MainActivity.java:

Но если повернуть экран, то активити пересоздастся и результата мы не увидим.

 

 

2. volatile, synchronized

Создадим вот такой класс:

И запустим его:

Мы создаём 2 потока. В одном увеличиваем число, а в другом уменьшаем. В результате по окончанию всех потоков у нас должно быть такое же число что и перед запуском потоков, т.е. =0. Но результат не всегда может быть таким. Дело в том, что данные могут быть закэшированы для потока и пока они находятся в кэше другой поток(из своего кэша) может записать свое значение в память. На помощь приходит volatile.

Он не позволяет хранить данные в кэше.

Помимо него есть synchronized. Он предоставляет единоличный доступ к данным. Пример:

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

Можно и так:

Что нам и подходит)).

 

3. wait(), notify(), notifyAll()

Эти методы есть у каждого класса. Они выполняются только внутри synchronized. synchronized блокирует объект, а после метода wait() объект разблокируется и выполнение команд остановится. Поток будет ждать пока у этого объекта не вызовут метод notify() или notifyAll() и тогда он сможет выполнять свои команды дальше. Метод notify() пробуждает только 1 поток. notifyAll() пробуждает все потоки (которые ждут пока разблокируется доступ к объекту), но выполняться начнёт только тот(поток) которому система предоставит доступ, остальные по-прежнему будут в режиме ожидания.

 

4. AsyncTask

AsyncTask может выполнять работу в другом потоке, а результат возвращать в главном потоке:

Обязательный метод только doInBackground(). AsyncTask<String, Integer, Integer> следует понимать как <параметры, прогресс, результат>. Используем:

В логах будет следующее:

Теперь сделаем так, чтобы результат возвращался в активити. Для этого добавим интерфейс Listener:

Используем:

 

5. HandlerThread

С помощью HandlerThread можно создать второй поток, который будет ждать задачи. Если задач нет, то поток не завершается, а переходит в режим ожидания.

Используем как синглтон:

Передаем задачи:

 

Ссылки:

  1. Thread
  2. Runnable
  3. Handler
  4. Процессы и потоки
  5. AsyncTask
  6. HandlerThread

Добавить комментарий

www.000webhost.com