1. Возврат данных через переменные и методы класса
Использование этого метода для возврата данных требует вызова метода start, прежде чем данные можно будет получить с помощью переменных или методов класса. Давайте сначала посмотрим, какие результаты мы получим из примера 2-13.
Скопируйте код кода следующим образом:
пакет мифрид;
публичный класс MyThread расширяет поток
{
частное строковое значение1;
частное строковое значение2;
публичный недействительный запуск()
{
value1 = "Вернуть данные через переменные-члены";
value2 = "Вернуть данные через метод-член";
}
public static void main(String[] args) выдает исключение
{
Поток MyThread = новый MyThread();
поток.start();
System.out.println("значение1:" + thread.value1);
System.out.println("value2:" + thread.value2);
}
}
Запуск приведенного выше кода может привести к следующим результатам:
Скопируйте код кода следующим образом:
значение1: ноль
значение2: ноль
Приведенные выше результаты бега выглядят очень ненормально. Значения были присвоены значениям value1 и value2 в методе run, но возвращается значение null. Причина, по которой это происходит, заключается в том, что значения значений value1 и value2 выводятся сразу после вызова метода start, а метод run здесь еще не выполнил операторы, присваивающие значения значениям value1 и value2. Чтобы избежать этой ситуации, вам нужно дождаться выполнения метода run, прежде чем выполнять код, который выводит значение1 и значение2. Поэтому мы можем подумать об использовании метода сна для задержки основного потока. Например, мы можем добавить следующий оператор после thread.start():
спать(1000);
Это может привести к тому, что основной поток задержит выполнение на 1 секунду, прежде чем продолжить, но здесь есть проблема: как узнать, на какое время задержать. В этом примере в методе run есть только два оператора присваивания, и создается только один поток. Поэтому задержки в 1 секунду достаточно, но если операторы в методе run сложные, это время трудно предсказать. Поэтому этот метод не стабилен.
Наша цель — получить значения value1 и value2, поэтому нам нужно только определить, являются ли value1 и value2 нулевыми. Если ни одно из них не равно нулю, эти два значения можно вывести. Для достижения этой цели мы можем использовать следующий код:
Скопируйте код кода следующим образом:
while (thread.value1 == null || thread.value2 == null);
Использование приведенного выше утверждения позволяет очень стабильно избежать этой ситуации, но этот метод потребляет слишком много системных ресурсов. Вы можете себе представить, что если код в методе run очень сложен, присвоение значения1 и значения2 займет много времени, поэтому цикл while должен продолжать выполняться до тех пор, пока и значение1, и значение2 не станут пустыми. Таким образом, мы можем внести следующие улучшения в приведенное выше утверждение:
Скопируйте код кода следующим образом:
while (thread.value1 == null || thread.value2 == null)
спать(100);
В цикле while после первой оценки значений value1 и value2 он засыпает на 100 миллисекунд, а затем оценивает эти два значения. Это займет меньше системных ресурсов.
Хотя описанный выше метод можно решить очень хорошо, модель потоков Java предлагает лучшее решение — метод соединения. Как обсуждалось ранее, функция соединения заключается в использовании потоков для перехода от асинхронного выполнения к синхронному. Когда поток становится синхронно исполняемым, это ничем не отличается от получения возвращаемых данных от обычного метода. Следовательно, эту проблему можно решить более эффективно, используя следующий код:
Скопируйте код кода следующим образом:
поток.start();
поток.join();
После выполнения thread.join() метод run потока потока завершился, что означает, что поток потока завершился. Поэтому вы можете смело использовать любой ресурс класса MyThread после thread.join() для получения возвращаемых данных.
2. Возврат данных через функцию обратного вызова
Фактически, этот метод был представлен в «Трех методах передачи данных в потоки». В примере статьи «Три метода передачи данных в потоки» результаты вычислений передаются в поток через метод процесса класса Work, но при этом из потока также получаются три случайных числа через метод процессный метод. Следовательно, этот метод может как передавать данные в поток, так и получать их из него.