2014-02-20 5 views
0

Наш учитель дал нам следующий код:join() не блокирует другие потоки (кроме основного)?

public static void main(String[]args) { 
Thread a = new Thread(new T(2)); 
Thread b = new Thread(new T(5)); 

a.start(); 
b.start(); 

try { 
a.join(); //Thread a now runs completely to the end, before the main-method gets back to a "runnable" state 

    b.join(); //Thread b runs to death before the main methods u 
    } catch (InterruptedException ie) {} 

    System.out.println("done"); //Result: Random Thread a and b outputs 
           //and in the end "done" from main 
    } 

public class T extends Thread { 
private int nr; 
public T(int nr) { 
this.nr = nr; 
} 

public void run() { 
for (int i=0; i<10; i++) { 
System.out.println("Hello " + nr + " " + i); 
} 
} 

Thread а и б одинаковы и оба пишут (в для цикла) 10 отпечатков на консоль. Потоки a и b завершены до того, как основной метод остановлен, и все результаты были случайными, за исключением основного метода.

Вопрос был, если он не должен блокировать другие потоки (а не только основные), если вы вызываете join() в одном потоке. Он сказал, что join() просто замораживает основной метод. Но по какой причине это должно быть хорошо? Он также сказал, что это совершенно случайно и управляется планировщиком, что, на мой взгляд, не имеет смысла для этой части (планировщик управляет состояниями потоков, это понятно, но не после вызова join(), по крайней мере а не для приложения Java. Или я ошибаюсь?). Моей точкой было бы то, что Thread a и b побежали полностью до конца, прежде чем основной поток даже назвал метод join. Джавадок говорит мне то же самое, если я понимаю это правильно.

Надеюсь, кто-то из вас может дать мне ответ. :)

ответ

3

Звонок по номеру join() по экземпляру Thread не будет завершен до тех пор, пока не исчезнет нить, соответствующая этому экземпляру.

Корроллар 1: если эта нить уже мертва, join() немедленно возвращается.

Corrollary 2: ни один из потоков, за исключением текущего, не влияет на этот вызов.

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

Вы, вероятно, не расслышал, что именно здесь сказал учитель. Планирование потоков, что означает принятие решений, когда потоку будет предоставлено некоторое время процессора для запуска, и сколько из него выполняется планировщиком потоков. Это определенно не «абсолютно случайный», и для большинства практических соображений все потоки выполняются все время. Опять же, это мало связано с поведением метода join.

+0

только мои 2 цента.Полностью случайный в этом контексте означает, что программист не имеет понятия, предсказывать или управлять, когда потоки будут выполняться или приостанавливаться. – holap

+0

@ holap Я возражаю против объединения «неуказанных» с «полностью случайным», потому что последнее на самом деле является гораздо более сильным * утверждением и позволяет выводить ложные выводы. –

+0

Я понял, что учитель хотел мне рассказать. Но так ли это? Действительно ли join() просто переносит поток в состояние «wait», а остальное - задача планировщика? Как поток может «подождать» для другого потока, если у него нет «власти», чтобы его дождаться (потому что Java не может самостоятельно управлять им). На самом деле этот метод звучит на 100% бесполезно для меня, если я не ошибаюсь. В любом случае, спасибо за ваш ответ! :) Я думаю, что это не совсем ясно, что я хотел спросить с моей стартовой страницей. Извините за мой английский. – codepleb

0

Пункт join не должен придавать ничью приоритет над всеми остальными. Скорее, это означает, что одному потоку нужно дождаться завершения другого потока до того, как этот (первый) поток может продолжить работу. Это не всегда основной поток, вызывающий join. Это ограничение ограничивается планировщиком: «Не делайте A, пока не сделаете B». Конечно, используя несколько join, вы можете выполнить более сложные зависимости.

0

Я подозреваю, что точка, которую пытался сделать ваш учитель, заключается в том, что вы не можете предположить ничего, кроме договора join. То есть основной поток не будет продолжаться до тех пор, пока не завершится a.

Вполне возможно a.join(), чтобы позволить b продолжать, но также возможно для того, чтобы полностью блокировать b до a завершения.

Если вы протестировали этот код на одноядерной машине, вполне вероятно, что a.join() исключает b, но на многоядерном компьютере это может не случиться.

Смежные вопросы