![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
jGorets |
|
|||
Новичок Профиль Группа: Участник Сообщений: 30 Регистрация: 11.7.2010 Репутация: нет Всего: нет |
Кто как или где и в каких случаях лучше создавать потоки через интерфейс Runnable или используя класс Thread??
|
|||
|
||||
soulcub |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 2.2.2010 Где: Винница, Украина Репутация: нет Всего: 2 |
То-есть вопрос можно перефразировать как "Зачем нужны потоки?".
Не люблю отвечать ссылками, но вопрос то ведь элементарный.. http://www.quizful.net/post/java-threads Тут неплохо написано про потоки. --------------------
Так давай же, поспеши!Отыскать СВОЙ куб души! |
|||
|
||||
nc30 |
|
||||||||
![]() Интересующийся :) ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 24.6.2010 Где: Санкт-Петербург Репутация: 5 Всего: 8 |
В двух словах: наследовать от Thread - более просто, реализовать Runnable - более гибко. Создать потоковый класс наследованием от класса Thread весьма просто: наследовал класс, переопределил метод run(), создал объект, запустил на выполнение. Но наследовать наш потоковый класс от какого-либо другого мы уже не сможем, т. к. родитель в Java может быть только один и он уже есть - класс Thread. Реализация интерфейса Runnable чуть более сложна в описании и требует несколько большего количества ресурсов. Все это происходит оттого, что класс, реализующий интерфейс Runnable - это еще не полноценный потоковый класс. Реализуя Runnable (определяя метод run()), мы объявляем, что объект теоретически способен к выполнению (able to be run), но настоящих потоковых методов (start(), wait() и еще с полсотни методов) у нашего класса нет. Для того, чтобы объект нашего класса действительно мог выполняться, ему нужен т. н. handler - управляющий поток. Handler - это полноценный поток, объект класса Thread. Образно говоря, он "взваливает" объект нашего класса (который - как мы уже выяснили - не совсем поток) к себе "на плечи" и полностью им управляет в отношении "потоковости", т. е. потоковые методы выполняются как раз handler'ом. К членам нашего класса, которые непосредственно не связаны с его "потоковостью", handler отношения не имеет. Другими словами, наш класс, реализуя интерфейс Runnable, заявляет, что он готов исполнить "потоковый" контракт, а handler момогает ему этот контракт выполнить. Все на самом деле очень просто ![]() Соответственно в этом случае (реализация Runnable), приходится чуть больше описывать. К тому же вместо одного объекта (как в случае наследования от Thread) создаются два - наш "поток" и управляющий поток. Зато этот вариант не связывает нам руки в отношении возможности наследования нашего класса, если это необходимо. А какой вариант выбрать - зависит от конкретной ситуации при разработке программы.
Это сообщение отредактировал(а) nc30 - 22.9.2010, 10:31 |
||||||||
|
|||||||||
Skipy |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 487 Регистрация: 24.8.2006 Где: Москва, Россия Репутация: 6 Всего: 16 |
Добавлю пару слов. Иногда необходимо вызвать извне методы класса Thread, чаще всего это join и interrupt. В этом случае по любому где-то придется держать ссылку именно на Thread. В случае, когда ссылка нужна еще и на экземпляр нашей реализации потока - например, выставить какой-нибудь флаг, забрать какие-нибудь данные и т.п. - имеет смысл их совместить при возможности, и унаследоваться от Thread.
|
|||
|
||||
nc30 |
|
||||||
![]() Интересующийся :) ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 24.6.2010 Где: Санкт-Петербург Репутация: 5 Всего: 8 |
Skipy, спасибо вам за дополнение
![]()
Это то, о чем вы говорите?
Не очень понял, что именно имеет смысл совместить. Можно чуть подробнее? Это сообщение отредактировал(а) nc30 - 22.9.2010, 13:46 |
||||||
|
|||||||
Skipy |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 487 Регистрация: 24.8.2006 Где: Москва, Россия Репутация: 6 Всего: 16 |
Не совсем. Внутри Вашего Runnable ссылку на поток получит ьне вопрос - Thread.currentThread(); Эта ссылка нужна вовне:
Ссылка t может понадобиться не сразу, а где-то в дальнейшем, когда надо прервать, например, этот поток, а он висит на мониторе. Флагом Вы этого не сделаете, а вот вызовом t.interrupt() ожидание на мониторе прерывается.
Допустим, Вы создали реализацию Runnable, и Вам необходимо иметь возможность вызывать у нее какие-то методы. Т.е. Вам нужно сохранить ссылку на экземпляр этой реализации. С другой стороны, Вам нужно иметь ссылку на поток, в котором этот экземпляр работает. Т.е. ссылок получается уже две, вп римере выше - это myRunnable и t. Вот чтобы не хранить две ссылки и не протаскивать их везде, где они нужны, можно унаследовать класс от Thread (а не от Runnable), и тогда ссылка нужна будет всего одна. |
||||||
|
|||||||
nc30 |
|
||||||||
![]() Интересующийся :) ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 24.6.2010 Где: Санкт-Петербург Репутация: 5 Всего: 8 |
Хорошо, предположим, есть класс:
В чем тогда ощутимое преимущество
перед
Управляющий поток, по сути, один и тот же. Просто во-втором случае ссылка на него хранится в самом объекте, что удобно. Или что-то здесь не так? ![]() Это сообщение отредактировал(а) nc30 - 22.9.2010, 18:56 |
||||||||
|
|||||||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
В том что MyRunnable может быть унаследован от любого класса. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
nc30 |
|
||||
![]() Интересующийся :) ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 24.6.2010 Где: Санкт-Петербург Репутация: 5 Всего: 8 |
LSD, Skipy
Да не вменятся мне мои посты в полемику с метрами программирования, просто действительно хочу разобраться ![]()
В примере выше, и в том, и в другом случае MyRunnable - один и тот же класс, он не наследует от Thread, а реализует интерфейс Runnable. Вопрос был несколько в другом. Skipy отметил следующее:
По логике поставленной передо мной задачи: 1) неудобно наследоваться от Thread; 2) неудобно хранить две ссылки и протаскивать их везде, где они нужны; 3) тем не менее иметь доступ к основному объекту и управляющему потоку. Что мне мешает сделать ссылку на управляющий тред в самом классе (см. мой последний пост) и управлять моим потоком через эту ссылку? В этом случае хранить и протаскивать (по отношению к основному объекту) нужно будет только ссылку на MyRunnable, и я, по идее, избегаю вышеперечисленных неприятностей. |
||||
|
|||||
Skipy |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 487 Регистрация: 24.8.2006 Где: Москва, Россия Репутация: 6 Всего: 16 |
В философии. Как только Вы открыли setHandler - его может использовать кто угодно. Не разобравшись, поставит туда другой поток. Кроме того, Можно вызвать getHandler до того, как будет вызван setHandler. Всё это лишние потенциальные проблемы. Если Вам неудобно наследоваться от Thread, но нужно иметь его экземпляр - хранение handler-а в самом Runnable есть хороший вариант. Я бы все-таки тогда сделал так:
Это лучше хотя бы тем, что Вы не светите set-метод, во-первых, и не позовете get-метод до инициализации handler-а во-вторых. |
||||
|
|||||
nc30 |
|
|||
![]() Интересующийся :) ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 24.6.2010 Где: Санкт-Петербург Репутация: 5 Всего: 8 |
Skipy, позволю себе еще уточнение. Какие минусы вы видите в следующей реализации?
Что меня привлекло в этом варианте: 1) Управляющий поток создается одновременно с основным объектом. Т. о. нет риска вызвать getHandler() до создания самого handler'а. 2) После создания потока (но перед его стартом) мы можем с ним проделать какие-то подготовительные действия (obj.getHandler().setPriority(), например). 3) Метод setHandler() действительно не нужен "во избежание" (в примере выше он использован для "похожести" наших ситуаций), здесь я с вами полностью согласен. Это сообщение отредактировал(а) nc30 - 23.9.2010, 10:07 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |