Вы не хватаете несколько важных моментов, о резьбе предполагая, что основной поток как-то собирается останавливаться и ждать, пока вновь созданный поток, чтобы выполнить его метод run()
перед возвращением.
При работе с потоками, имейте в виду следующее:
- Когда вы запускаете поток в методе
GetAddress()
это не означает, что она будет называть это немедленно запустить метод и просто приступить к возвращению вычисленного адреса, когда возвращается, как если бы вы вызвали метод run, не создавая новый поток. Вы бы даже не нуждались в другом потоке, если бы хотели этого. Когда вы запускаете второй поток, вы в основном сообщаете ОС, что есть новый поток, готовый к запуску, но он зависит от ОС, чтобы точно решить, когда действительно начнется код в этом потоке. Даже в среде с несколькими CPU/ядрами вы не можете предположить, что ядро будет доступно в этой точке.
Вы также не можете предположить, что основной поток остановится или приостановит его выполнение только потому, что он запустил другой поток. Основной поток может в конечном итоге прекратить выполнение в течение короткого времени, чтобы другие потоки могли выполняться, но только тогда, когда в системе недостаточно ядер для запуска всех потоков параллельно. В любом случае вы не можете предсказать, когда или произойдет это. Это означает, что после запуска нового потока гораздо вероятнее, что метод GetAddress()
продолжит возвращать текущее значение адресной переменной своему вызывающему абоненту до завершения только что созданного потока или даже начать его метод run()
.
Если вы не уверены в том, что истинно, то попробуйте вставить следующие строки после запуска нити:
thread.start();
try { // Used just for demonstration purposes
thread.join(); // This block kills the parallelism of the second thread
}
return address;
Этот код заставляет основной поток ждать вновь созданного потока для выполнения.Обратите внимание, что этот код испортит любые преимущества создания нового потока.
Так что же теперь?
У вас есть много способов борьбы с несколькими потоками, и я не могу рассказать вам, что является лучшим методом, не зная намного больше о вашем проекте; но я могу дать вам несколько направлений на очень простом примере.
Предположим, у вас есть программа с пользовательским интерфейсом, кнопка для получения адреса и текстовое поле, в которое будет записан адрес. Когда кто-то нажимает кнопку, вместо того, чтобы пытаться вычислить адрес одним выстрелом, вы вызываете метод вроде startRetrievingAddress()
, в котором вы должны запустить рабочий поток и заполнить текстовое поле временным текстом, например "please wait..."
. В конце метода рабочего потока run()
вы можете добавить код, чтобы заполнить текстовое поле окончательным результатом.
Еще лучший способ сделать это - создать класс рабочих потоков с поддержкой «слушателей», которые будут уведомлены, когда метод запуска будет выполнен с использованием адреса, чтобы они имели возможность иметь дело с результатами, как только они вычисляются. Затем вы зарегистрируете слушателя, в котором вы должны установить текстовое поле с вычисленным значением. Уверены, что есть еще лучшие способы сделать это, используя поток петлителя, чтобы иметь дело с сообщениями, выпущенными из рабочих потоков, и все, но я не могу назвать их всех здесь. Удачи!
вы оставили блоки блокировки пустыми. Добавьте 'e.printStackTrace();' для каждого блока catch и проверьте, не выбрано ли исключение – Blackbelt
, вы только что начали тему. Как вы ожидаете, что «адрес» будет заполнен? – njzk2