почему этот код
public static void main(String [] argv){
Logger l = LoggerFactory.getLogger( "MAIN" );
Thread thread = new Thread(()->{
Logger ll = LoggerFactory.getLogger( "WRKR" );
ll.debug("start t1");
try {
Thread.sleep( 10000 );
} catch (InterruptedException e) {
throw new RuntimeException( e );
}
ll.debug("end t1");
}) ;
l.info("main");
thread.start();
try {
Thread.sleep( 8000 );
} catch (InterruptedException e) {
throw new RuntimeException( e );
}
try {
l.info("trying to join");
thread.join(100);
l.info("joined");
} catch (InterruptedException e) {
throw new RuntimeException( e );
}
l.info("end main");
}
производит этот вывод:
10:57:38.871 [main] INFO MAIN - main
10:57:38.879 [Thread-0] DEBUG WRKR - start t1
10:57:46.884 [main] INFO MAIN - trying to join
10:57:46.993 [main] INFO MAIN - joined
10:57:46.993 [main] INFO MAIN - end main
10:57:48.880 [Thread-0] DEBUG WRKR - end t1
Какой смысл join(100) не сообщать, что «рабочий» поток все еще работает? Я ожидал исключения во время выполнения.
Ваш вопрос требует мнений и, следовательно, не по теме. Первоначальные разработчики считали, что если вы хотите подождать только X миллисекунд, вам не нужно информироваться и вам следует проверить себя. С тех пор они решили иначе с join(Duration). Однако они не могут изменить это для существующих методов, поскольку это было бы критическим изменением, чего они не делают.




Javadoc для метода join(long millis) гласит: «Ожидает не более миллимиллисекунд, пока этот поток завершится». Он не сообщает о текущем состоянии другого потока, поэтому после вашего звонка thread.join(100); у вас не будет никакой информации о состоянии thread.
Начиная с JDK19, вы можете использовать join с Duration, который возвращает логическое значение, сообщающее, завершился ли поток. Если вы просмотрите исходный код join(Duration), он эквивалентен join(millis); с тестом isTerminated();, поэтому вы можете вызвать thread.isTerminated(), если в данный момент не используете JDK19+.
Приятно знать! В любом случае, к сожалению, я все еще использую Java 17.
В Javadoc для t.join(duration) говорится: «Возврат:...false, если поток не завершился». Это ложь. Возвращаемое значение false не означает, что поток все еще работает. Это означает только то, что время ожидания соединения истекло. Мы можем предположить, что поток работал в какой-то момент до истечения времени ожидания вызова соединения, но у нас нет возможности узнать, как давно это было.
@SolomonSlow Тогда это не ложь. Конечно, он не может сообщить о состоянии потока после возврата метода...
@MarkRotteveel, документация является явной. В нем говорится, что возвращаемое значение false означает, что поток не завершился. Какой смысл говорить, что возвращаемое значение X означает Y, если Y не гарантированно станет истинным к моменту проверки значения вызывающим объектом? Правдивое описание возвращаемого значения будет означать, что false означает, что время ожидания вызова истекло, и поток в этот момент может все еще работать, а может и не работать.
@SolomonSlow Да, и это именно то, что он возвращает, если вы посмотрите на код (я посмотрел код Java 21). Возвращаемое значение является результатом Thread.isTerminated(). Другими словами, в момент возврата метода он возвращает состояние завершения. Он не может предсказать будущее, поэтому, если поток завершится на наносекунду позже, он, очевидно, не сможет сообщить об этом.
Если возвращаемое значение не предсказывает будущее, то документация в лучшем случае вводит в заблуждение. И, что вводит в заблуждение, так это то, что это вводит младших разработчиков в заблуждение, заставляя их не думать о том, как состояние некоторого объекта может быть изменено потоком A после того, как поток B запросил его состояние, но до того, как B сможет действовать с информацией. Такое недоразумение, если его не остановить, может привести к архитектурным недостаткам реального коммерческого программного обеспечения.
@SolomonSlow Он не может предсказать будущее: он знает только, каким было состояние на момент возвращения, и в то время оно было либо прекращено, либо все еще работало. Хотя ваш аргумент, вероятно, иллюстрирует, почему старые методы join не имеют возвращаемого значения (хотя вы, вероятно, тогда возразите, что запрос Thread.isTerminated() также не может предсказать будущее и, следовательно, вводит в заблуждение...).
«Я ожидал исключения во время выполнения». Почему? В документации указаны только два исключения: «Выдает:
IllegalArgumentException— если значение миллис отрицательноеInterruptedException— если какой-либо поток прервал текущий поток. Статус прерванного текущего потока очищается, когда выдается это исключение». тайм-аут не указан (метод завершается нормально, никаких исключений не происходит)