- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
public class ServiceRunner implements Runnable {
Thread thread = null;
ServiceUI service;
public ServiceRunner(ServiceUI service) {
this.service = service;
}
public void start() {
this.thread = new Thread(this);
this.thread.start();
}
public void run() {
while (true) {
this.service.receiveMessages();
try {
this.thread.sleep(CommonConst.INTERVAL_SERVICE * 1000);
} catch (java.lang.InterruptedException e) {
Log.log(Log.ERROR,this,e);
}
this.service.sendMessages();
try {
this.thread.sleep(CommonConst.INTERVAL_SERVICE *1000);
} catch (java.lang.InterruptedException e) {
Log.log(Log.ERROR,this,e);
}
}
}
очень удивляют предыдущие разрабочтики продукта своими понятиями о потоках в Java
new Thread(Runnable r); а не наоборот? =)
засыпает, потому, что после выхода его по след разу запускают.
стоит отдать должное тому, что код работает, но поддерживать его
и тем более обновлять практически невозможно.
new Thread(Runnable r); а не наоборот? =)
а что в этом не так? По-моему, натурально, что любой обьект может желать запустить свой метод run() в отдельном потоке, при этом ему самому не обязательно быть наследником Thread
ну нет в яве делегатов, че поделать?
2). если объекту нужно запустить свой runnable, то проблема в дизайне архитектуры кода
3). при таком подходе из-вне нету доступа к внутреннему Thread поэтому данные умники реализовывали в их Runnable методы isRunning, stop, start, которые по хорошему должны быть у Thread.
> ну нет в яве делегатов, че поделать?
дожить до jdk-7 при текущем функционале ;)
2. это проблема отсутствия делегатов: в яве приходится плодить кучу вспомогательных (чаще анонимных) классов, это и потоки (упомянутый Runnable), и слушатели событий и смежные проблемы.
3. если мы, как в примере, делаем приватное поле типа Thread, то методы isRunning, stop, start по хорошему должны быть именно тут.
У Thread когда-то были метод stop, но, поскольку он убивал поток мгновенно и жестоко, то вместо пересмотра архитектуры его обьявили вообще deprecated, а управление потоками теперь приходится писать каждый раз заново.
>дожить до jdk-7 при текущем функционале ;)
впрочем, лазейки есть. Например, создать аннотацию @Listener(Event) и аннотировать ею методы класса, обработчиком аннотаций прозрачно передавая управление (видел такое в Tapestry5)
1). логичный вызов new Thread(Foo); приведёт к нелогичной работе
2). нету доступа к объекту потока изне, в результате появляются шедевры вида http://govnokod.ru/4170 про реализацию join(timeout) я уже не пишу.
3). interrupted Exception при таком подходе остаётся внутри runnable метода, что тоже не логично (в этом куске кода плохо видно).
Это не значит, что использование Thread внутри Runnable всегда не верно, т.к. есть варианты, где нужно предоставить многопоточность в вызове Run. Данная реализация к таким не относится.
По поводу 3го пункта, вы точно уверены, что в jdk-6 не появилось новых механизмов управления потоками ;) ?
а AOP и его реализации это отдельный разговор.
Cовершенно верно, это более общий интерфейс для выполнения какой-то задачи, и не обязательно понимать его как поток (как неплохая иллюстрация: методы invokeLater и invokeAndWait класса SwingUtilities)
> Другое его использование приведёт минимум к непониманию
Другое его использование означает непонимание его назначения
> Поэтому Foo не должен заниматься созданием _единственного_ потока для своего выполнения
Он должен заниматься логичной обработкой потоков. Он должен создавать поток (или потоки, например, в пуле), стартовать и, если нужно, останавливать поток(потоки) - при этом он не обязан реализовывать Runnable - хотя он может это делать, но тогда накладываются упомянутые ограничения на его использование, и для решения этой проблемы либо документируем соглашения (не создавать более одного потока и т.д.), либо проектируем его интерфейс (набор публичных методов) так, что бы исключить его некорректное использование
> вы точно уверены, что в jdk-6 не появилось новых механизмов управления потоками ;) ?
Насколько мне известно, нет. Если я что-то пропустил, буду удивлен ))
что и было продемонстрировано авторами кода. у которых _все_ Runnable содержали в себе Thread. и потом работа с ними из-вне выглядела весьма коряво (ссылка в комментарии выше)
> Он должен заниматься логичной обработкой потоков...
не буду спорить, что такой класс имеет право на жизнь и он будет верен. Однако в данному коду он не относится :). Хотя наверное мой код не полон без примера вызова данного метода, где все проблемы видны :)
насчёт последнего моего комментария отпишусь позже )
.
ну я был не совсем точен.
изменения пошли с jdk-5, а в 6 были расширены. напр
изменения реализации групп потоков, Executor[Service], у которого уже есть shutdown, работающий корректно (относительно stop) и т.д. (в т.д. разбираюсь плохо)
вот именно
Если говорить о AOP в полноценном виде, хотя бы тот же AspectJ, который расширяет язык Java (новые ключевые слова и т.д.)
Сквозное программирование силами Java (с помощью аннотаций, допустим) я не считаю AOP, хотя во многих случаях такие AOP-подобные замашки очень даже удобны
Например:
аннотация @Test в JUnit4, позволяющая не придерживаться соглашения имен public void test*()
Tapestry5 декораторы методов и сервисов (http://tapestry.apache.org/tapestry5/tapestry-ioc/decorator.html)
Tapestry5 обработчики событий
(http://tapestry.apache.org/tapestry5/guide/event.html)
другие аннотации декорирования для логгирования, профайлинга и проч.
Все это не AOP, а скорее лишь AOP-style