2016-09-29 28 views
0

我写了一个House类,它有四个同步方法。 我写了四个线程,并希望他们一个接一个地运行。但只是第一次和第二次跑,另一次没有?如何使用wait()和notifyAll()逐个运行线程?

public class House { 

    private boolean hasFoundation = false; 
    private boolean hasFrame = false; 
    private boolean hasWall = false; 
    private boolean hasRoof = false; 

    public synchronized void buildFoundation() { 
     hasFoundation = true; 
     System.out.println("foundation Ok"); 
     notifyAll(); 
    } 

    public synchronized void buildFrame() throws InterruptedException { 
     if (!hasFoundation) { 
      wait(); 
     } else { 
      hasFrame = true; 
      System.out.println("frame ok"); 
      notifyAll(); 
     } 
    } 

    public synchronized void buildWall() throws InterruptedException { 
     if (!hasFrame) { 
      wait(); 
     } else { 
      hasWall = true; 
      System.out.println("wall ok"); 
      notifyAll(); 
     } 
    } 

    public synchronized void buildRoof() throws InterruptedException { 
     if (!hasWall) { 
      wait(); 
     } else { 
      hasRoof = true; 
      System.out.println("roof ok"); 
      notifyAll(); 
     } 
    } 
} 

public class BuildAHouse { 

    public static void main(String[] args) { 
     House house = new House(); 

     ExecutorService exec = Executors.newCachedThreadPool(); 

     exec.execute(new FoundationTeam(house)); 
     exec.execute(new WallTeam(house)); 
     exec.execute(new RoofTeam(house)); 

     exec.execute(new FrameTeam(house)); 

     exec.shutdown(); 
    } 
} 

运行时,在main(),结果只是: 基础确定 框架确定

其他两个线程运行没有带!为什么?

的... Team类是这样的:

public class FoundationTeam implements Runnable { 

    private House house; 

    public FoundationTeam(House house) { 
     this.house = house; 
    } 

    @Override 
    public void run() { 
     house.buildFoundation(); 
    } 

} 

这只是一个演示,我想知道如何使用wait()和notifyAll的()。

请解决这个问题好吗?它只是我想要的一部分。 请告诉我为什么它不起作用,以及如何解决?

当调用wait()时,这个对象会不会被释放?和其他线程不能调用其他同步方法?

+0

我不知道你在那些'... Team'类中,但你可能只执行一次该方法。线程被暂停,当他们得到通知时,他们继续退出该方法,因为他们从来没有机会进入这个else子句,除了'FrameTeam' – kevto

+0

我不认为你真的需要'wait()'和'notifyAll()':这里已经有'ExecutorService',这是更高层次的同步抽象。请参阅http://stackoverflow.com/q/2153663/5521491 –

+0

我不认为这是正确的用例。无论你想要实现这一点,都可以轻松实现。 例如等待通知: 1.生产者消费者 2.偶奇打印机使用2线程 3.使用3个线程以顺序方式打印数字 – cody123

回答

2

如果你的方法并等待(),它是不会运行在else

注意什么:)等(可不合逻辑唤醒,建议while循环。

+0

方法调用wait(),其他调用notifyAll()不能唤醒? – Oolong

+0

@Oolong如果你等待()你没有做其他事情。 –

0

这是工作!

public synchronized void buildWall() throws InterruptedException { 
    while (!hasFrame) { 
     wait(); 
    } 
    hasWall = true; 
    System.out.println("wall ok"); 
    notifyAll(); 
} 

添加“while()”,但我不知道为什么!

+0

因为你需要等待,直到'hasFrame'成立。 'wait'函数不知道它正在等待什么,也无法分辨它是否等待发生。所以这是你的责任。 –

1

另外两个线程不能运行!为什么?

正如@Peter提到的那样,你已经想通了,你需要在等待循环周围循环使用while(!boolean)。这有几个原因是必要的。

正如Peter提到的那样,wait()可能会因虚假唤醒而不是正确调用notify()而返回。您需要确保您正在等待的条件已经设置好,然后循环并再次拨打wait()(如果没有)。

然而,就你而言,关于虚假唤醒和更多关于如何编写程序的内容不多。因为您有一个​​对象(House对象),所以当您调用notifyAll()时,所有队线程都被唤醒。当调用buildFoundation()方法时,它将hasFoundation设置为true并唤醒所有团队。但是只有框架团队才能真正开始工作 - 其他团队需要循环并等待更多,直到他们的布尔值被设置为true。

您可以更改您的代码以使用不同的锁定每个步骤使代码更容易遵循,虽然您仍然需要while循环。

最后,正如你已经知道的那样,你的if ... else ...模式没有意义,因为当团队等待时,当他们被通知时,他们的构建方法将会返回,因为其他东西在else

相关问题