Урок 80. Handler. Немного теории. Наглядный пример использования

Обсуждение уроков
Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Foenix » 11 авг 2013, 03:29

да, ты прав, с этой штукой нужно или INVISIBLE или GONE
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

nubodroid
Сообщения: 28
Зарегистрирован: 19 ноя 2012, 08:20

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение nubodroid » 18 авг 2013, 22:33

Всем доброй ночи, прошу прощения... чем отличается Thread.start() от ExecutorService.executor(Runnable);

Просто... решил попробовать сделать живые обои... нарыл кучу статей и... в рез-те вернулся на форум. Просто во всех статьях каждый делает по своему... Основной принцип понятен, но из-за вот таких ExecutorService(пример из книги Эд Бурнет "Привет, Андроид! Разработка мобильных приложений")... Просто я в Java новичок совсем... Параллельно читаю.

Всем заранее спасибо

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Mikhail_dev » 19 авг 2013, 14:32

Ну на сколько я понял, прочитав вскользь ExecutorService, это просто пул потоков. Т.е. это много вот таких вот "Thread.start". Сам Thread.start, запускается в одном, новом потоке.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение altwin » 09 дек 2013, 19:32

Почитав не много тему - все таки не удержался - простите :)
MeTeOpA писал(а):В Java насколько я знаю поток можно создать 2мя способами .
Это глубочайшее заблуждение и скажите, неужели действительно думаете, что гениальность многопоточности java была бы возможна, если бы сие было правдой?

Начнем с того, что врятли имеет смысл перечислять количество способов запуска потока, однако если тема интересна, я бы очень рекомендовал ознакомиться с Сервисом запуска потоков в java (ExecutorService), к примеру:

Код: Выделить всё

ExecutorService service = Executors.newFixedThreadPool(4);
for(int i = 0; i < 10; i++) {
            service.submit(
                //Some operetions here...
            );
        }
, код внутри service.submit выполниться 10 раз используя 4 потока. для чего кстати сам код описывается в методе call(), а класс наследует Callable<Т>. И не просто потому. что Runnable надоело.... ExecutorService очень интересная тема и помимо newFixedThreadPool, есть еще несколько методов thread safe, позволяющих выполнять в том числе и отложенные действия...
Так же работая с потоками не стоит забывать про java.util.concurrent.locks.Lock и java.util.concurrent.atomic.AtomicInteger, последний к слову позволяет делать вычисления с простыми типами(к примеру инкремент счетчика) так же thread safe... т.е. пример того, что volatile int - не даст ничего(суть в примитивности типа), а вот AtomicInteger исключает блокировки... Так же очень важным аспектом являются синхронизаторы(к примеру - Semaphore, защелка(CountDownLatch), цикличный барьер(CyclicBarrier)).
К чему бы я это ? да все просто - Android - это java... и то, что разработчики упростили нам жизнь тем, что добавили Handler(по сути просто реализации модели многопоточности коллекций одним из способов(к слову далеко не самым оптимальным)), не говорит о том, что стоит забыть остальное и верить в многопоточность приложения лишь выполняя в фоне загрузку части UI... Это всего лишь итератор на основе стандарта:

Код: Выделить всё

Iterator<E> iter = collection.iterator();
и вся работа Hendler основана по принципу:

Код: Выделить всё

iter.hasNext();
iter.next();
iter.remove();
, т.е. обработки событий передвижения по коллекции.
Модель многопоточных коллекций java содержит не только работу с очередью, а к примеру такие интересные вещи, как - неблокирующая синхронизация, безопасный итератор. CopyOnWriteArrayList, ConcurrentSkipListSet, ConcurrentMap
no-- писал(а):Ну на сколько я понял, прочитав вскользь ExecutorService, это просто пул потоков. Т.е. это много вот таких вот "Thread.start". Сам Thread.start, запускается в одном, новом потоке.
начнем с того, что как минимум с помощью метода Call (inerface Callable<T>) можно реализовать вычисления в отдельном классе(вынести туда Lock -и и Semaphor - ы). Но как потом запустить? В ручную создавать потоки, далее объекты класса и т.д.? ExecutorService - дает очень мощный и безопасный способ запуска(к слову он и является сервисом запуска потоков) и предоставляет кучу очень мощных средств контроля в том числе отложенных вычислений и т.д. Хотя судя по тому, что я написал - это врятли что -то объясняет) но простите я не умею объяснять... могу лишь порекомендовать ознакомиться поглубже с книжкой Java Concurrency in Practice, понять все преимущества, а иногда и то, что без подобных инструментов не возможно работать можно понять только используя на реальных задачах.

P.S. это мое разглагольствование не покрывает и половины возможностей java... Но сказать я хотел лишь одно - не надо строить иллюзии, что Handler спасет мир...
Изображение

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение altwin » 09 дек 2013, 19:50

nubodroid писал(а):Всем доброй ночи, прошу прощения... чем отличается Thread.start() от ExecutorService.executor(Runnable);

Просто... решил попробовать сделать живые обои... нарыл кучу статей и... в рез-те вернулся на форум. Просто во всех статьях каждый делает по своему... Основной принцип понятен, но из-за вот таких ExecutorService(пример из книги Эд Бурнет "Привет, Андроид! Разработка мобильных приложений")... Просто я в Java новичок совсем... Параллельно читаю.

Всем заранее спасибо
Thread().start создает объект класса Thread и запускает его, класс ExecutorService содержится в java.util.concurrent.ExecutorService, т.е. это другой класс и он не создает поток а лишь содержит инструменты эффективной работы с ним. Для того, чтобы его использовать Необходимо реализовать метод call() интерфейса callable, преимуществ очень много, но очевидны они там где много потоков и много вычислений, там где нужны высокоуровневые и надежные средства обработки... Новичку в java для начала я бы рекомендовал понять что такое deadlock и как с ним бороться... научиться использовать synchronize и только потом учиться обходиться без него и работать потокобезопастно... хотя по сути правильная архитектура данных может заменить все... но в реальной жизни -это практически не возможно :)
Изображение

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение altwin » 09 дек 2013, 19:57

altwin писал(а):
nubodroid писал(а):Всем доброй ночи, прошу прощения... чем отличается Thread.start() от ExecutorService.executor(Runnable);

Просто... решил попробовать сделать живые обои... нарыл кучу статей и... в рез-те вернулся на форум. Просто во всех статьях каждый делает по своему... Основной принцип понятен, но из-за вот таких ExecutorService(пример из книги Эд Бурнет "Привет, Андроид! Разработка мобильных приложений")... Просто я в Java новичок совсем... Параллельно читаю.

Всем заранее спасибо
Thread().start создает объект класса Thread и запускает его, класс ExecutorService содержится в java.util.concurrent.ExecutorService, т.е. это другой класс и он не создает поток а лишь содержит инструменты эффективной работы с ним. Для того, чтобы его использовать Необходимо реализовать метод call() интерфейса callable, преимуществ очень много, но очевидны они там где много потоков и много вычислений, там где нужны высокоуровневые и надежные средства обработки... Новичку в java для начала я бы рекомендовал понять что такое deadlock и как с ним бороться... научиться использовать synchronize и только потом учиться обходиться без него и работать потокобезопастно... хотя по сути правильная архитектура данных может заменить все... но в реальной жизни -это практически не возможно :)

P.S. да кстати похоже я забыл упомянуть главное, то, что дает нам Callable<T> - это как минимум возможность возвращать значение из потока, и например передавать данные между потоками( что -то вроде наличия "глобальной переменной" доступной любому потоку)... но это далеко не все, тут есть не только методы позволяющие управлять запуском, но к примеру высокоуровневые методы синхронизации(CountDownLatch, CyclicBarrier, ThreadLocal), к сожалению трудно вот так просто вспомнить, когда все, что есть в голове - помню - это круто :) По сути -это наработанный десятками лет сообществом java опыт многопоточной работы собранный в одном месте и решающий известные проблемы эффективно.
Изображение

qualitat1ve
Сообщения: 6
Зарегистрирован: 18 фев 2013, 10:55

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение qualitat1ve » 02 янв 2014, 19:24

Я так понимаю для 1 потока нельзя создать несколько хендлеров? Как быть если мне надо запустить 2 фоновых потока, каждый из которых должен иметь доступ к компонентам UI?

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение altwin » 02 янв 2014, 20:23

qualitat1ve писал(а):Я так понимаю для 1 потока нельзя создать несколько хендлеров? Как быть если мне надо запустить 2 фоновых потока, каждый из которых должен иметь доступ к компонентам UI?
Хендлер не имеет отношения к runnable. Вы можете запускать, что угодно, но если потоков более одного lock/syncronize перед помещением в хендлер- ваша проблема. Хендлер по сути просто формирует очередь сообщений для главного потока и иметь более одного бессмысленно. Вам нужно вручную синхронизировать потоки либо, что удобней использовать lock, опять же есть различные executors для запуска потоков, вариантов куча -это же java.
Изображение

bigbaak
Сообщения: 5
Зарегистрирован: 27 апр 2014, 20:16
Откуда: Казахстан

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение bigbaak » 02 май 2014, 18:43

Помогите с потоками. Я делаю проект, который создает мульти подключение через Wifi и отправляет всех подключивщихся потоковый аудио. Аудио записывается с помощью AudioRecorder в один массив.На деле, получился так: массив доступен первому кто-то подключился, а другие ждут этот массив.что делать?

bayah
Сообщения: 5
Зарегистрирован: 07 апр 2014, 15:01

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение bayah » 16 май 2014, 16:20

Доброй ночи, товарищи.
Подскажите, пожалуйста.

Я хочу сделать 2 потока(ну основной UI и еще один поток). Эти потоки должны мочь "общаться" друг с другом, то есть посылать друг другу сообщения.
В уроке реализована возможность из созданного потока отослать сообщение в основной UI-поток. А как сделать, чтобы из UI-потока отправить сообщение в созданный поток?

Вообще это мне нужно, чтобы сделать плеер, проигрывание музыки в котором должно быть в отдельном потоке. Таким образом, чтобы управлять проигрыванием нужно будет отсылать сообщения из UI-потока в поток проигрывателя.
Или как-то иначе надо?)

Аватара пользователя
Leeroy
Сообщения: 67
Зарегистрирован: 12 дек 2013, 21:25

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Leeroy » 16 май 2014, 21:12

bayah писал(а):Доброй ночи, товарищи.
Подскажите, пожалуйста.

Я хочу сделать 2 потока(ну основной UI и еще один ......
.....отсылать сообщения из UI-потока в поток проигрывателя.
Или как-то иначе надо?)
AsyncTask в помощь
Java Core -> JDBC -> GoF -> Android SDK ->...
Телепрограмма в твоем смарте Телепрограмма

Viewer
Сообщения: 180
Зарегистрирован: 30 апр 2014, 11:42

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Viewer » 16 май 2014, 21:21

bayah писал(а): В уроке реализована возможность из созданного потока отослать сообщение в основной UI-поток. А как сделать, чтобы из UI-потока отправить сообщение в созданный поток?
Handler привязан к тому потоку, в котором он создается. В данном уроке Handler создается в UI-потоке (в onCreate() Activity), поэтому он к нему и "привязан".

bayah
Сообщения: 5
Зарегистрирован: 07 апр 2014, 15:01

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение bayah » 17 май 2014, 16:55

Leeroy писал(а):
bayah писал(а):Доброй ночи, товарищи.
Подскажите, пожалуйста.

Я хочу сделать 2 потока(ну основной UI и еще один ......
.....отсылать сообщения из UI-потока в поток проигрывателя.
Или как-то иначе надо?)
AsyncTask в помощь

А что AsyncTask? Ну да, я в курсе, что можно передавать данные в поток, но там ведь только в начале данные можно передать, перед стартом, а не в произвольный момент времени?

Насчет Runnable.
Зачем он вообще нужен? Почему и для чего в уроке мы передаем его в Thread?
Разве нельзя унаследоваться от Thread, определить себе необходимые функции и вызывать в них необходимый себе код?
Я сделал так:

Унаследовал класс от Thread и внутри создал Handler для связи из основного UI-потока с созданным потоком:

Код: Выделить всё

  public class MyThread extends Thread {
	  
	  public Handler h_in;

	  public MyThread(Runnable runnable){
		  super(runnable);
		  h_in = new Handler() {
			  public void handleMessage(android.os.Message msg) {
				  h.sendEmptyMessage(msg.what);
			  }
		  };
	  }
  }
В основном потоке создаем Handler для него же:

Код: Выделить всё

     
	    h = new Handler() {
	      public void handleMessage(android.os.Message msg) {
	        // обновляем TextView
	        tvInfo.setText("Пришло сообщение: " + msg.what);
	     }
Далее создаем поток(run тут ни зачем):

Код: Выделить всё

	      t = new MyThread(new Runnable() {
	    	  public void run() {
	        	int a = 10;
	          } 
	      });
По кнопке отсылаем сообщение в Handler созданного потока:

t.h_in.sendEmptyMessage(11);
Поток в свою очередь отсылает сообщение Handler'у основного UI-потока и тот уже отображает его.
То есть сообщение ушло и вернулось как бы.

Так вот. Зачем нам Runnable и правильно ли я все понял или какую-то чушь нагородил?)

Viewer
Сообщения: 180
Зарегистрирован: 30 апр 2014, 11:42

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Viewer » 17 май 2014, 17:34

bayah писал(а):
Так вот. Зачем нам Runnable и правильно ли я все понял или какую-то чушь нагородил?)
Не совсем
h_in = new Handler() {...
должно быть внутри метода run(){}, код который выполняется внутри этого метода и будет код вашего нового потока.
А код конструктора класса MyThread будет выполняться в том потоке в котором создается объект этого класса, т.е. в вашем случае тоже в UI-потоке

И еще - вот этот код int a = 10;, который у вас новом потоке, отработает за тысячные доли секунды, а если вы будете посылать сообщения в отработавший поток, то скорее всего получите исключение. Вам нужны более долгоживущие потоки ))

bayah
Сообщения: 5
Зарегистрирован: 07 апр 2014, 15:01

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение bayah » 18 май 2014, 02:00

Viewer писал(а):
bayah писал(а): И еще - вот этот код int a = 10;, который у вас новом потоке, отработает за тысячные доли секунды, а если вы будете посылать сообщения в отработавший поток, то скорее всего получите исключение. Вам нужны более долгоживущие потоки ))
Ну тем не менее я уже посылал сообщение и оно обрабатывалось и возвращалось. Исключений не было.

Viewer
Сообщения: 180
Зарегистрирован: 30 апр 2014, 11:42

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Viewer » 18 май 2014, 11:20

bayah писал(а): Ну тем не менее я уже посылал сообщение и оно обрабатывалось и возвращалось. Исключений не было.
Потому и не было исключений, что сообщения отправляются в UI-потоке и принимаются в UI-потоке , см. первую часть моего поста.

А вообще Handler не применим к потоку в том виде в котором вы его написали. Handler применяется только к тем потокам у которых есть Looper (петля) т.е. к потокам, которые не завершаются отработав какой-то код, а переходят в режим приема сообщений (они еще называются "Looper Thread", UI-поток именно таковым и является). Т.е. Looper это фактически цикл обработки сообщений, который организует обработку сообщений в порядке очереди, без него отправлять сообщения просто некуда.
[syntax=java] class MyThread extends Thread {
public Handler h;

public void run() {
Looper.prepare();

h = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
Log.d(TAG, "handleMessage_quit");
Looper.myLooper().quit();
} else {
Log.d(TAG, "handleMessage-"+msg.what);
}
}
};

Looper.loop();
Log.d(TAG, "QUIT");
}
}[/syntax]

Запускаем поток как обычно
[syntax=java]MyThread t = new MyThread();
t.start();[/syntax]

Отправляем сообщения потоку
[syntax=java]t.h.sendEmptyMessage(1);
//Сообщение для завершения потока
t.h.sendEmptyMessage(0);[/syntax]

ЗЫ Кстати, сообщения отправленные отработавшему, неактивному потоку не вызывают исключения, но и не выполняются, т.е. отправляются в никуда и метод sendEmptyMessage() возвращает false в этом случае.

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение klblk » 19 май 2014, 07:32

bayah писал(а):Доброй ночи, товарищи.
Подскажите, пожалуйста.

Я хочу сделать 2 потока(ну основной UI и еще один поток). Эти потоки должны мочь "общаться" друг с другом, то есть посылать друг другу сообщения.
В уроке реализована возможность из созданного потока отослать сообщение в основной UI-поток. А как сделать, чтобы из UI-потока отправить сообщение в созданный поток?

Вообще это мне нужно, чтобы сделать плеер, проигрывание музыки в котором должно быть в отдельном потоке. Таким образом, чтобы управлять проигрыванием нужно будет отсылать сообщения из UI-потока в поток проигрывателя.
Или как-то иначе надо?)
Service... другие варианты для плеера мне кажутся ненадежными.

bayah
Сообщения: 5
Зарегистрирован: 07 апр 2014, 15:01

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение bayah » 19 май 2014, 16:20

Viewer писал(а):
bayah писал(а): Ну тем не менее я уже посылал сообщение и оно обрабатывалось и возвращалось. Исключений не было.
Потому и не было исключений, что сообщения отправляются в UI-потоке и принимаются в UI-потоке , см. первую часть моего поста.

А вообще Handler не применим к потоку в том виде в котором вы его написали. Handler применяется только к тем потокам у которых есть Looper (петля) т.е. к потокам, которые не завершаются отработав какой-то код, а переходят в режим приема сообщений (они еще называются "Looper Thread", UI-поток именно таковым и является). Т.е. Looper это фактически цикл обработки сообщений, который организует обработку сообщений в порядке очереди, без него отправлять сообщения просто некуда.
[syntax=java] class MyThread extends Thread {
public Handler h;

public void run() {
Looper.prepare();

h = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
Log.d(TAG, "handleMessage_quit");
Looper.myLooper().quit();
} else {
Log.d(TAG, "handleMessage-"+msg.what);
}
}
};

Looper.loop();
Log.d(TAG, "QUIT");
}
}[/syntax]

Запускаем поток как обычно
[syntax=java]MyThread t = new MyThread();
t.start();[/syntax]

Отправляем сообщения потоку
[syntax=java]t.h.sendEmptyMessage(1);
//Сообщение для завершения потока
t.h.sendEmptyMessage(0);[/syntax]

ЗЫ Кстати, сообщения отправленные отработавшему, неактивному потоку не вызывают исключения, но и не выполняются, т.е. отправляются в никуда и метод sendEmptyMessage() возвращает false в этом случае.

Вот оно как. Мерси за Looper - не знал.)
Я тут подумал еще. А если делать плеер через класс MediaPlayer, то разве он не выполняется в новом потоке сам по себе?

klblk писал(а): Service... другие варианты для плеера мне кажутся ненадежными.
А почему именно Service?

Viewer
Сообщения: 180
Зарегистрирован: 30 апр 2014, 11:42

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Viewer » 19 май 2014, 16:37

Почитайте http://developer.android.com/guide/topi ... layer.html там все подробно расписано, в т.ч. и про асинхронную подготовку MediaPlayer чтобы не весить UI-поток

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение klblk » 20 май 2014, 05:51

bayah писал(а):
klblk писал(а): Service... другие варианты для плеера мне кажутся ненадежными.
А почему именно Service?
Интуитивно как-то =) Длительная задача, не зависит от ui и не убивается "случайно" Андроидом. Service в режиме iddqd, wakelock и нотификашка (как бонус).
Подробнее дали ссылку выше, а именно пункт Using a Service with MediaPlayer

Ответить