2014-05-14 21 views
1

我有这样一个类:Java并发:一些援助

package crossRoadConcurency; 

import java.util.List; 

public class TourGuide 
{ 
    private volatile boolean isGuiding; 
    private volatile boolean isInShop; 
    private final Object lockObject = new Object(); 
    private final int id; 

    public TourGuide(int id) 
    { 
     this.isGuiding=false; 
     this.isInShop=false; 
     this.id=id; 
    } 

    public synchronized boolean isFree() 
    { 
     return !isGuiding && !isInShop; 
    } 

    public void guide(final Tourist[] tourists) 
{ 
    new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      synchronized (lockObject) 
      { 
       while(!isFree()) 
       { 
        try 
        { 
         System.out.println("Guide "+id+" is bussy. Waiting... "); 
         lockObject.wait(); 
        } 
        catch (InterruptedException e) 
        { 
         e.printStackTrace(); 
        } 
       } 
      } 
      isGuiding=true; 
      System.out.println("Guide "+id+" is guiding "+tourists.length+" tourists"); 
      try 
      { 
       Thread.sleep(4000);//lets not wait one hour, shall we? 
       for (Tourist tourist : tourists) 
       { 
        tourist.exit(); 
       } 
       System.out.println("All tourists exited for guide "+id+". Going to shop"); 
       isInShop=true; 
       isGuiding=false;//if we invert the way we give these values bad thing may happen 
       Thread.sleep(4000); 
       isInShop=false; 
       System.out.println("Guide "+id+" is free"); 
       synchronized (lockObject) 
       { 
        lockObject.notifyAll(); 
       } 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 

     } 
    }).start(); 
} 
} 

而另一个类:

package crossRoadConcurency; 

import java.util.Random; 

public class Tourist 
{ 
    public void exit() throws InterruptedException 
    { 
     Random random = new Random(); 
     Thread.sleep(random.nextInt(1000));// max one second to exit 
    } 
} 

,我用这样的:

package crossRoadConcurency; 

import java.util.List; 

public class Main 
{ 

    public static void main(String[] args) throws InterruptedException 
    { 
     Tourist[] tourists = new Tourist[20]; 
     for (int i=0;i<tourists.length;i++) 
     { 
      tourists[i]=new Tourist(); 
     } 
     TourGuide guide = new TourGuide(0); 
     guide.guide(tourists); 
      Thread.sleep(500); 
     guide.guide(tourists); 

    } 

} 

的问题是我得到这个输出:

Guide 0 is guiding 20 tourists 
All tourists exited for guide 0. Going to shop 
Guide 0 is free 
Exception in thread "Thread-0" Guide 0 is guiding 20 tourists 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60) 
    at java.lang.Thread.run(Unknown Source) 
All tourists exited for guide 0. Going to shop 
Guide 0 is free 
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60) 
    at java.lang.Thread.run(Unknown Source) 

第一个问题:为什么我没有看到“等待输出”
第二个问题:为什么我会得到一个异常
第三个问题:有没有更好的方式来做到这一点,因为我相当肯定这个概念是混淆

回答

1
  1. 你没有看到“等待”,因为你的向导是默认免费。 !isGuide && !isInShop返回true,而您仅在!isFree()时打印。

  2. 您应该致电lockObject.notifyAll()。直接调用notifyAll()默认情况下调用此对象,并且您肯定没有执行实现Runnable接口的Anoymous对象的监视器,因为您从来没有通过调用synchroized(this)执行此操作。这就是你得到这个例外的原因。

  3. 是的。您应该使用Executor,例如SingleThreadExecutor以及一个并发队列。除非您继续进行高性能计算,否则这是实现并发性的强大且简单的方法。该软件包还提供了出色的功能和支持功能类。检查出java.util.concurrent

顺便说一句,您的软件包名称包含不受java编程规范推荐的大写字母。

+0

1.默认情况下他,但看到主要的方法 - 我有2个电话指导方法,其中第二个应该赶上繁忙模式的指导。 2.请参阅编辑的问题。我仍然得到异常 –

+0

你启动了2个线程,但是你可以在任何线程将它们设置为true之前先让这两个线程检查这个标志。 –

+0

@ user3580294但是这并没有用,因为他在方法内部启动另一个线程并运行它。在那个线程里面,他依赖于lockObject。您在该方法上同步只会导致线程的创建和启动被同步。 –

-1

当我们同步任何块或方法时,我们应该对类锁或对象锁进行同步。

但在这里,你已经锁定某些对象,它是没有地方有关该方法的调用者

所以改变这种从下面synchronized (lockObject)喜欢和运行

synchronized (this) 
+0

如果你在'lockObject'看到OP的调用'wait()'和'notifyAll()',所以我认为'synchronized'块是正确的 – awksp

+0

ha我把输出像下面那样放在同步后(this)指南0是bussy 。等待... 指南0指导20名游客 所有的游客都为参考0而退出。去商店 指南0是免费的 –

+0

...我实际上没有得到OP的代码例外......所以也许不是那个部分这是扔掉的东西。 – awksp