Передача одного запускаемого объекта нескольким конструкторам потоков

Если я создаю runnable object

Runnable run = new MyRunnable();

И затем передайте один и тот же точный объект двум конструкторам потоков и запустите их

new Thread(run).start;
new Thread(run).start;
  • Возможно ли это? Каковы последствия?
  • Если я вызываю Thread.sleep(0); в классе MyRunnable будут ли обе нити засыпать, потому что они являются одним и тем же объектом, или сущность потока полностью отделена от объекта?
  • Будет ли когда-нибудь причина для этого, если не все равно ответьте на два вопроса выше, потому что я не думаю, что я полностью понимаю механизм потоков?

Ответ 1

  • Это определенно возможно и законно. Если ваш Runnable не имеет состояния (без полей), тогда все будет в порядке. Если ваш Runnable имеет изменяемое состояние, вам может потребоваться использовать один из многих механизмов взаимного исключения Java, например ReentrantLock или ключевое слово synchronized. Поскольку обе потоки будут мутировать поля одного и того же объекта Runnable.

  • Нет, вы создали и запускали две разные темы. Они просто называют Runnable.run().

  • Это не из сферы возможностей. Я бы даже не сказал, что это плохая практика. Конкретные ситуации, в которых вы могли бы сделать это, оставались в качестве упражнения для читателя...

Ответ 2

1) Возможно ли это? Каковы последствия?

Да, это возможно.

Импликация заключается в том, что любое состояние в Runnable (потенциально) разделяется всеми потоками, а доступ к/обновлению этого состояния должен быть правильно синхронизирован.

2) Если я вызываю Thread.sleep(0); в классе MyRunnable будут обе спящие потоки, потому что они являются одним и тем же объектом, или сущность потока полностью отделена от объекта?

Нет, они не будут.

Тема логически отлична от Runnable. Вызов Thread.sleep() напрямую не влияет на Runnable и другие потоки, которые могут его использовать. (Это может повлиять на другие потоки косвенно, например, если один поток спящий, в то время как он удерживает Runnable-примитивный замок, а другие потоки должны получить блокировку для достижения прогресса.)

3) Было бы когда-нибудь причина для этого, если бы не все еще ответили на два вопроса выше, потому что я не думаю, что я полностью понимаю механизм потока?

Вы можете сделать это, если не существует связанного с потоком состояния, связанного с Runnable, и вы хотели бы минимизировать накладные расходы на время или накладные расходы инициализации Runnable. Но такие практики редко встречаются на практике.

В подавляющем большинстве случаев использования в реальном мире каждый поток нуждается в отдельном экземпляре Runnable.