2013-08-13 3 views
-4

Программа создает поток t0, который порождает поток t1, а затем создаются потоки t2 и t3. После выполнения потока t3 приложение никогда не возвращается к другим потокам, порожденным ранее (t0, t1, t2) и они остаются застрявшими.Java thread join 3

Зачем нужны нитки t0, t1 и t2?

 public class Cult extends Thread 
      { 
       private String[] names = {"t1", "t2", "t3"}; 
       static int count = 0; 
       public void run() 
       { 
        for(int i = 0; i < 100; i++) 
        { 
         if(i == 5 && count < 3) 
         { 
          Thread t = new Cult(names[count++]); 
          t.start(); 
          try{ 
           Thread.currentThread().join(); 
          } 
          catch(InterruptedException e) 
          { 
           e.printStackTrace(); 
          } 
         } 
         System.out.print(Thread.currentThread().getName() + " "); 
        } 
       } 

       public static void main(String[] a`) 
       { 
        new Cult("t0").start(); 
       } 
      } 
+1

Вы, вероятно, хотите 't.join()' 'не Thread.currentThread() присоединиться();' – Gray

+0

@Gray:. То есть именно то, что я ищу. t.join() выполняется правильно с окончанием t3 и t0 заканчивается последним. Но что происходит, когда мы используем Thread.currentThread.join()? Почему t0, t1, t2 приостановлены посередине? –

ответ

2

Наиболее важный момент вы пропустили:

Thread.currentThread().join(); 

Метод join в исходном коде используется isAlive метод.

public final synchronized void join(long millis) 
    ... 
    if (millis == 0) { 
     while (isAlive()) { 
     wait(0); 
     } 
    ... 
    } 

Это означает, что Thread.currentThread().join() вернется только тогда, когда Thread.currentThread() мертв.

Но в вашем случае это невозможно из-за вашего кода в Thread.currentThread() имеет себя этот мир кода Thread.currentThread().join(). Вот почему после завершения Thread 3 ваша программа должна висеть, и после этого ничего не происходит.

enter image description here

1

Почему нити t0, t1, t2 и приостановлено? Выполнение потока t3 завершается.

t3 завершается, потому что это не пытается раскошелиться на 4-ю нить и, следовательно, не пытается join() с его собственным потоком. Следующая строка никогда не вернется так t0, t1, t2 и все остановки там и ждать навсегда:

Thread.currentThread().join(); 

Это просит текущий поток ждать самого закончить, который не работает. Я подозреваю, что вы хотели сказать t.join();, который ждет нитку, которая была только раздвоена, чтобы закончить.

Вот некоторые другие мысли о вашем коде ни в кажущейся порядке:

  • Вы должны рассмотреть implements Runnable вместо extends Thread. См. Здесь: "implements Runnable" vs. "extends Thread"

  • Вы используете переменную staticcount в нескольких потоках без защиты от блокировки. Лучшим решением является использование AtomicInteger вместо int. У вас, вероятно, нет проблемы, потому что каждый поток изменяет count, а затем накладывает другой поток, но если вы попытаетесь развить 2 потока, это будет реальной проблемой из-за условий гонки данных.

  • Я не уверен, почему вы только порождаете другую нить if(i == 5 && count < 3). i будет только 5один раз в этом цикле. Это действительно то, что вы намеревались?

  • String[] names = {"t1", "t2", "t3"}; поля рекомендуется указывать на топ классов. В противном случае они попадают в код и теряются.

  • В main вы начинаете резьбу Cult, а затем завершаете основную нить. Это не нужно, и вы можете просто позвонить cult.run(); в main и использовать основную тему.

  • Cult(String s) { super(s); } Нет смысла иметь конструктор, который вызывает супер конструктор с теми же аргументами. Это можно удалить.

  • Это спорный вопрос, но я стараюсь положить метод main в верхней части класса и не похоронить его, так как это метод «входа». То же самое с конструкторами. Это должно быть выше метод run().

  • catch(Exception e) {}действительно плохой рисунок. По крайней мере, вы должны сделать e.printStackTrace(); или зарегистрировать его как-то. Захват и просто исключение исключает лот проблем. Кроме того, ловлю Exception следует изменить на catch(InterruptedException e). Вы хотите ограничить блоки блокировки только исключениями, брошенными блоком, иначе это может снова скрыть проблемы в будущем, если вы скопируете и вставьте этот блок где-нибудь.

  • Более эффективная практика, но никогда не используйте константы, такие как 3, которые должны соответствовать другому элементу данных. В этом случае было бы лучше использовать names.length, который равен 3. Это означает, что вам не нужно менять 2 места в коде, если вы хотите увеличить количество потоков. Вы также можете иметь имя "t" + count и полностью избавиться от массива names.