2013-06-12 6 views
2

моя задача - создать поток в этом порядке: если A start-> start B и C, если B start-> start D. И уничтожить их в обратном порядке Если D тогда B. Если B и C то А. Надеюсь, вы это поняли. Мне это удается, но я думаю, что есть лучший способ сделать это. Есть ли у вас какие-либо предложения?синхронизированное выполнение нити

После ваших комментариев я изменил свой код, и это намного проще. Но теперь это выглядит «глупо». Я хотел бы изменить хардкор, если заявления и реализация, любые советы? tnx за советом Я учусь с тобой.

Это мой новый код:

 import java.util.*; 
class RobotController implements Runnable{ 
String name; 

public void run() { 
    Thread t = Thread.currentThread(); 
    System.out.println(t.getName() + " status = " + t.isAlive()); 
    System.out.println(t.getName() + " status = " + t.getState()); 

    } 

public static void main(String args[]) throws InterruptedException{ 
    Thread thread_A = new Thread(new RobotController(), "Thread A"); 
    Thread thread_B = new Thread(new RobotController(), "Thread B"); 
    Thread thread_C = new Thread(new RobotController(), "Thread C"); 
    Thread thread_D = new Thread(new RobotController(), "Thread D"); 

    thread_A.start(); 
    thread_A.join(); 
    System.out.println(thread_A.getState()); 
    thread_B.start(); 
    thread_B.join(); 
    System.out.println(thread_B.getState()); 
    thread_C.start(); 
    thread_C.join(); 
    System.out.println(thread_C.getState()); 
    thread_D.start(); 
    System.out.println(thread_D.getState()); 


} 

} 
+0

Похоже, вы должны определить задачу («Runnable») с родительским полем того же типа и булевским флагом, чтобы убить его. –

+0

вы синхронизируете локальную переменную * метода *, это бессмысленно. –

+0

'if A start-> start B и C' этим значением u означает, что после того, как' A' завершит свою работу, тогда 'B' начнется в последовательности .. и после того, как' B' завершает свою работу, тогда начинается 'C'? –

ответ

3

Есть некоторые недостатки в вашем коде, которые делают его не работать, соответственно, иногда:

  1. Вы назвали thread_A.start(), а затем проверил thread_A.isAlive(). Теперь, если, thread_A уже завершен до thread_A.isAlive(), условие проверено ?. thread_B и thread_C никогда не запускается. Ваше приложение не работает.
  2. Предположим, что thread_A не завершено, и thread_A.isAlive() условие передано, тогда начало thread_B до thread_C не всегда гарантируется планировщиком потоков Java. Снова ваше приложение выходит из строя.
  3. Предположим, что thread_B начинается до thread_C и если thread_B завершается до thread_B.isAlive() проверяется то условие if терпит неудачу и thread_D никогда не начал. Снова ваше приложение выходит из строя.

Теперь точка задуматься:
Там нет необходимости проверять, если поток жив после того, как его метод join() называется. Это лишние накладные расходы.

EDIT
OK, Вот модифицированная версия code..I надеюсь, что это позволит вам понять динамику резьбы:

class RobotController implements Runnable 
{ 
    private final Object lock = new Object(); 
    private void notifyThread() 
    { 
     synchronized(lock) 
     { 
      lock.notify(); 
     } 
    } 
    public void run() 
    { 
     synchronized(lock) 
     { 
      try 
      { 
       System.out.println(Thread.currentThread().getName() + " started"); 
       lock.wait(); 
       System.out.println(Thread.currentThread().getName()+ " stopped"); 
      } 
      catch (InterruptedException ex) 
      { 
       ex.printStackTrace(); 
      } 
     } 
    } 

    public static void main(String args[]) throws InterruptedException 
    { 
     RobotController rca = new RobotController(); 
     RobotController rcb = new RobotController(); 
     RobotController rcc = new RobotController(); 
     RobotController rcd = new RobotController(); 


     Thread thread_A = new Thread(rca,"Thread A"); 
     Thread thread_B = new Thread(rcb,"Thread B"); 
     Thread thread_C = new Thread(rcc,"Thread C"); 
     Thread thread_D = new Thread(rcd,"Thread D"); 

     thread_A.start(); 
     while (thread_A.getState() != Thread.State.WAITING) 
     { 
      Thread.sleep(100); 
     } 
     thread_B.start(); 
     thread_C.start(); 
     while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING) 
     { 
      Thread.sleep(100); 
     } 
     thread_D.start(); 
     while (thread_D.getState() != Thread.State.WAITING) 
     { 
      Thread.sleep(100); 
     } 
     rcd.notifyThread(); 
     thread_D.join(); 
     rcc.notifyThread(); 
     thread_C.join(); 
     rcb.notifyThread(); 
     thread_B.join(); 
     rca.notifyThread(); 
    } 

} 

А вот выход:

Thread A started 
Thread B started 
Thread C started 
Thread D started 
Thread D stopped 
Thread C stopped 
Thread B stopped 
Thread A stopped 
+0

tnx за то, что помог мне.Теперь я изменил свой код в соответствии с @Darshan Mehta, но я до сих пор не знаю, как решить проблему. Я не знаю, как и где я должен поставить эти условия. У вас есть идеи? Ps: я обновляю свой новый код. – njamanjam

+0

@njamanjam: Посмотрите на мое обновление .. –

+0

Tnx так много, я понимаю это сейчас намного лучше. – njamanjam

2

В многопоточной, нет необходимости синхронизации, если общие данные не используется несколькими потоками. В вашем случае вы хотите запустить и остановить потоки в определенном порядке. Для этого существует метод join в классе Thread. Ссылка This показывает хороший пример метода соединения.

+0

'join' не разрешает _concurrent_ выполнение потоков, только последовательный –

+0

Да. Но последовательность выполнения, требуемая здесь, может быть достигнута только путем объединения. Возможно, мы можем поместить вызов соединения в последнюю строку кода выполнения потока для достижения максимального параллелизма. –

+0

Теперь, после обзора кода OP, я думаю, что мой комментарий неактуальен) –

0

На мой взгляд, довольно странно использовать synchronized (lock) в вашем методе запуска, чтобы заблокировать ваш объект. Причина в том, что в каждом объекте Thread есть другой атрибут lock, который принадлежит каждому объекту. Это означает, что вы пытаетесь заблокировать разные объекты. На самом деле, это не имеет смысла.

В принципе, объектом, которым вы должны применить , являются любые общие объекты. Например, вам нужно что-то подсчитать, а затем вы создаете объект класса, чтобы поделиться им в своем классе. В этом случае он должен быть заблокирован во время чтения или записи.

+0

Блокировка разделяется между run() и stop_do(). Синхронизация необходима для вызова wait/notify. – fgb

+0

@fgb Конечно, но не имеет смысла блокировать атрибуты объекта вместо общего объекта. – lvarayut

+0

@Maverick это швы, что я просто не получил это. У вас есть пример, чтобы показать мне это на практике? – njamanjam

0

Я хотел бы выделить две точки здесь:

  1. Посмотрите на выполнение потока жизненного цикла here. В нем говорится, что при вызове метода start() поток входит в состояние runnable, а не в состояние выполнения. Когда поток входит в текущее состояние, это означает, что метод run() получает exexuted. CPU/OS решает приоритет, из которого поток должен быть перенесен из runnable в текущий поток. Например. если вы вызываете метод start() для 4 потоков, нет необходимости, чтобы они выполнялись в этом конкретном порядке. (Выполнение той же программы в моем компьютере несколько раз дает мне разные выходы.

В вашем случае, когда выполняется условие, если (thread_A.isAlive()) выполняется, то возможно, что поток А не может быть ( ). Для исправления этого поведения в основном должен выполняться цикл while, который ожидает, пока нить станет живой, и т. д.

2. В вашем программа, вы не назначили имена для потоков, и вы печатаете имя в методе run(). В этом случае JVM назначает имена потокам в порядке их выполнения, например, первый поток для выполнения будет иметь имя как «Thread- 0 'и т. Д. Следовательно, мы не будем способный определить, какой поток выполняется первым. Назначьте имена с помощью метода setName().

+0

tnx за помощь мне. Я узнал больше о потоках. Теперь я исправил свою программу, и потоки начинаются в порядке A-B-C-D, но после того, как метод соединения закончен, как я могу это исправить? Я пытался найти его в Интернете, но почему-то я не нашел ничего полезного. Ps: i обновил мой код – njamanjam

+0

Сначала попробуйте запустить все потоки, а затем вызвать соединение. –

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