2010-10-20 3 views
2

У меня есть 3 потока (A, B, C), которые я просто не могу заставить их работать, как я их хочу. ВСЕ эти 3 потока имеют ссылку на один и тот же объект - K. То, что я пытаюсь сделать, - это запустить все 3, а затем в некоторый момент времени, когда поток А попадает в определенное состояние, приостанавливает потоки B и C, пока не выполняет какой-то метод работы(), а когда работа заканчивается, резюме B и C.Java Thread Wait-Notify

Теперь то, что я в моем коде: Thread а имеет ссылку на как B и C. B и C есть метод pause() {synchronized (K) {k.wait; }} Когда A прибывает в определенном состоянии, я вызываю метод run() FROM A: B.pause(), C.pause(). Теперь то, что я ожидаю, это то, что Threads B и C будут waiT до тех пор, пока кто-то не сделает: k.notifyAll(), НО вместо Thread A остановится. Это нормально в java?

Код:

class A implements Runnable { 
    private K k; 
    private B b; 
    private C c; 

    void run() { 
     while(something) { 
     //do something 
     b.pause(); 
     c.pause(); 
      // !!! here this thread will freeze and doSomething2 wont get executed. 
      // what i want is to pause B, C, doSomething2 to get executed and then resume B and C 
     //do something2 
     synchronized(k) { 
      k.notifyAll(); 
     } 
     } 
    } 
} 
class B implements Runnable { 
    private K k; 


    void run() { 
     while(something) { 
     //dome something 
     } 
     } 
    } 
    public pause() { 
     synchronized(k) { k.wait();} 
    } 
} 
class C implements Runnable { 
    private K k; 


    void run() { 
     while(something) { 
     //dome something 
     } 
     } 
    } 
    public pause() { 
     synchronized(k) { k.wait();} 
    } 
} 
+0

Чтобы сделать это obviou что происходит. В классе B.run введите System.out.println (Thread.currentThread(). GetId()); и в B.pause делать то же самое. K.wait() на самом деле ждет другого потока (как говорили другие участники) –

+0

Когда вы говорите паузу, вы имеете в виду немедленно остановиться или закончить то, что вы делаете, тогда остановитесь и подождите, пока я не скажу, что вы можете продолжить? – BigMac66

ответ

0

Вы уверены, что вы называете b.pause(), но объявить B.sleep()?

Было бы неплохо увидеть конструкцию резьбы/код запуска.

3

Для реализации этого параметра вы можете использовать CylcicBarrier.

CyclicBarrier barrier = new CyclicBarrier(); 

public void run() { 
    new Thread(new A(barrier)).start(); 
    new Thread(new B(barrier)).start(); 

    barrier.await(); // Waits until all threads have called await() 

    // Do something 
} 

public void A implements Runnable { 
    private CyclicBarrier barrier; 

    public A(CyclicBarrier barrier) { 
     this.barrier = barrier; 
    } 

    public void run() { 
     barrier.await(); 
     // Do something. 
    } 
} 

public void B implements Runnable { 
    private CyclicBarrier barrier; 

    public B(CyclicBarrier barrier) { 
     this.barrier = barrier; 
    } 

    public void run() { 
     barrier.await(); 
     // Do something. 
    } 
} 
+2

Всегда лучше использовать классы параллелизма вместо механизма ожидания/уведомления нижнего уровня, если это возможно. – wolfcastle

+1

Я знаю, но это домашняя работа, и мне нужно использовать wait-notify. – Blitzkr1eg

0

Вы знаете, что используете 3 разных предмета (мониторы) A.k, B.k, C.k?

Итак, когда B «приостановил», он синхронизируется на собственном мониторе (B.k), который должен быть свободен в любом случае. Ваши потоки не «общаются» каким-либо образом.

+0

Он сказал, что они делились ссылкой на один и тот же объект, так что все должно быть хорошо. Проблема в том, что он блокирует вызывающий поток, как сказал @Benoit Thiery. – wolfcastle

0

Удалите звонки b.pause() и c.pause() от A.run() и позвоните им по их собственным методам запуска.

0

Если я не понимаю ваше домашнее задание, я думаю, вам нужно научиться прерывать поток. B и C - прерывистые потоки, которые должны обрабатывать прерывание таким образом, чтобы они не возобновлялись, пока им не сказали, что это нормально. Это может выглядеть примерно так:

while(true) 
{ 
    try 
    { 
     Thread.sleep(100); 
     System.out.println("Thread is working normally..."); 
    } 
    catch(InterruptedException e) 
    { 
     System.out.println("Thread has been interrupted, will wait till A is done..."); 
     try 
     { 
     synchronized(monitor) 
     { 
      monitor.wait(); 
     } 
     } 
     catch(InterruptedException e2) 
     { 
     // whatever... 
     } 
    } 
} 

Так что объект, работающий в своем потоке, будет иметь ссылки на два других потока. Объект A будет иметь доступ к общему объекту монитора, к которому также имеют доступ исполняемые файлы в двух других потоках (я назвал его monitor). Когда A прерывает другие потоки, их runnables затем вызывает wait() на мониторе. Когда A будет выполнен, он вызовет notifyAll() на мониторе.ПРИМЕЧАНИЕ. Вы должны также очистить флаг прерывания в других потоках, но я оставляю это для вас, чтобы выяснить - его легко :)

0

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

class A implements Runnable { 
    private K k; 
    private B b; 
    private C c; 

    void run() { 
     while(something) { 
     //do something 
     b.pause(); 
     c.pause(); 
      // !!! here this thread will freeze and doSomething2 wont get executed. 
      // what i want is to pause B, C, doSomething2 to get executed and then resume B and C 
     //do something2 
     synchronized(k) { 
      k.notifyAll(); 
     } 
     } 
    } 
} 
class B implements Runnable { 
    private K k; 
    volatile boolean isPaused = false; 


    void run() { 
     while(something) { 
     if (isPaused) { 
      synchronized(k) { k.wait();} 
      isPaused = false; 
     } 
     //dome something 
     } 
    } 
    public pause() { 
    isPaused = true; 
    } 
} 
class C implements Runnable { 
    private K k; 
    volatile boolean isPaused = false; 


    void run() { 
     while(something) { 
     if (isPaused) { 
      synchronized(k) { 
      k.wait(); 
      } 
      isPaused = false; 
     } 
     //dome something 
     } 
    } 
    public pause() { 
    isPaused = true; 
    } 
} 

Я предполагаю, что вы действительно хотите сделать, хотя безусловно ожидание вызова in in k in B и C и затем всегда звоните уведомите обо всем A