2015-11-21 11 views
3

Вот мой пример кода.Как сделать два потока ждать друг друга?

class A implements Runnable{ 

//stuff 
Thread thr = new Thread(this); 
boolean flag; 
public void run() 
{ 
    while(true){ 
     if(condition)flag = true; 
    } 
} 
} 



class B implements Runnable{ 

//stuff 
A a = new A(); 
Thread thr = new Thread(this); 
public void run() 
{ 
    while(true){ 
    //i ll do some thing here 
    if(a.flag == true)System.out.println("Kaboom"); 
    } 
} 
public static void main(String[] args) 
{ 
    B b = new B(); 
} 
} 

Так дело в том, я начать б перед и я хочу б не ждать, пока a.flag == истинный огонь «Kaboom» и a.thr должны ждать, когда б делать свою работу в перспективе() метод. Я пробовал это, но он не работает

class A implements Runnable{ 

//stuff 
Thread thr = new Thread(this); 
boolean flag; 
public void run() 
{ 
    while(true){ 
     if(condition)flag = true; 
    synchronized(B.class){ 

     this.flag=true; 
     B.class.notifyAll(); 
    } 
    } 
} 
} 



class B implements Runnable{ 

//stuff 
A a = new A(); 
Thread thr = new Thread(this); 
public void run() 
{ 
    while(true){ 
    synchronized(this){ 

     while(a.flag!=true) 
     { 
      this.wait(); 
     }} 
    } 
} 
public static void main(String[] args) 
{ 
    B b = new B(); 
}} 

Должно возникнуть проблема в моем синхронизированном блоке, но я не знаю, что.
Это, наверное, глупый вопрос, но я просто новичок в JAVA, и я действительно не получаю этот материал Thread и как он работает. Plz help me

+0

Рассматривали ли вы использование Thread.Join() таким образом, что A должен закончиться до начала B. https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html – JamesDonnelly

+0

метод join() убьет поток, и я не хочу, чтобы это произошло – Anonymous

ответ

1

Мне нравится ваш оригинальный подход использования ожидания/notifyAll, чтобы нить не использует процессор, пока условие не будет выполнено для того, чтобы возобновить работу. Вот решение, которое поддерживает такой подход.

Несколько замечаний:

1 - Будьте осторожны при синхронизации на объект класса. Если вы действительно не хотите синхронизировать весь класс, создайте объект и используйте его как блокировку.

2 - Используйте ключевое слово volatile, чтобы гарантировать, что Java не создает нить локальную версию переменной и которая изменяет ее значение, мгновенно отражается на других потоках.

public class Threads { 
    private final Object lock = new Object(); 
    private volatile boolean flag; 

    class RunnableA implements Runnable { 
     private volatile boolean condition = false; 
     @Override 
     public void run() { 
      while (true) { 
       if (condition) { 
        if (!flag) { 
         synchronized (lock) { 
          System.out.println("Setting Flag to True"); 
          flag = true; 
          lock.notifyAll(); 
         } 
        } 
       } else { 
        System.out.println("Condition is False"); 
        try { 
         Thread.sleep(500); 
        } catch (InterruptedException ex) { 

        } 
       } 
      } 
     } 
    } 

    class RunnableB implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       while (flag == false) { 
        synchronized (lock) { 
         if (flag == false) { 
          try { 
           lock.wait(); 
          } catch (InterruptedException ex) { 

          } 
         } 
        } 
       } 
       System.out.println("Kaboom"); 
      } 
     } 
    } 

    public void run() { 
     RunnableA runnableA = new RunnableA(); 
     RunnableB runnableB = new RunnableB(); 
     Thread t1 = new Thread(runnableA); 
     Thread t2 = new Thread(runnableB); 
     t1.start(); 
     t2.start(); 
     try { 
      Thread.sleep(5000L); 
     } catch (InterruptedException ex) { 

     } 
     runnableA.condition = true; 

    } 
    public static void main(String[] args) { 
     new Threads().run(); 
    } 
} 
+0

Спасибо за помощь ур, но это, похоже, не работает в моем случае. Могу ли я поставить свою проблему таким образом. Значит, вы все знаете, что игра змейка? Моя идея состоит в том, чтобы создать 2 runnable класса, класс A - змеиная головка (нажмите стрелку, и она будет двигаться, пока не достигнет края), и класс B для кадра, чтобы случайным образом генерировать «пищу» в кадре. Рамка может генерировать только пищу, если предыдущая еда уже съедена. Таким образом, объект B должен ждать, пока объект не съест пищу. Не могли бы вы рассказать мне, как сделать эту работу сэр? – Anonymous

+0

Я думаю, что ключом здесь является сброс флага на false после того, как змея съела пищу, но я не знаю, куда ее поставить. – Anonymous

+0

Итак, всякий раз, когда голова «съедает» пищу, вам нужно сбросить флажок и вызвать уведомление о блокировке, которую вы используете в потоке создателя пищи. Просто используйте тот же поток, который использует поток. Сказав это, есть ли какая-то особая причина для создания игры как многопоточной? Обычно проще создать его однопоточным. – andreban

0

Вы создали Runnable, но не запустили его в потоке.

Надлежащих один:

import java.lang.*; 
import java.util.concurrent.atomic.*; 

class A implements Runnable { 
    AtomicBoolean flag; 
    AtomicBoolean condition; 

    A() { 
     flag = new AtomicBoolean(); 
     condition = new AtomicBoolean(); 
    } 

    public void run(){ 
     while (true) { 
     System.out.println("A"); 
     if (condition.get()) { 
      flag.set(true); 
      return ; 
     } 
     try { 
      Thread.sleep(1000); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
     } 
    } 
} 

class B implements Runnable { 
    A a; 

    B() { 
     a = new A(); 
    } 

    public void run() { 
    while (true) { 
     System.out.println("B"); 
     if (a.flag.get()) { 
      System.out.println("Kaboom"); 
      return ; 
     } 
     try { 
      Thread.sleep(1000); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    } 

    public static void main(String[] args) { 
     B b = new B(); 
     new Thread(b).start(); 
     new Thread(b.a).start(); 
     b.a.condition.set(true); 
    } 
} 
+0

Я назвал thr.start() в конструкторе уже – Anonymous

+0

@ ChiếnTrần Обновлено. Кстати, вы можете прочитать книгу «Java Concurrency in Practice», которая действительно великолепна. – jiegec

+0

i sure will, thanks anw – Anonymous

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