我有一个这样的课程:
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)
第一个问题:为什么我没有看到“等待输出”
第二个问题:为什么我会收到例外
第三个问题:有没有更好的方法来做到这一点,因为我相当肯定这个概念已经混淆了
答案 0 :(得分:1)
你没有看到&#34;等待&#34;因为您的指南默认是免费的。只在!isGuide && !isInShop
时打印时!isFree()
返回true。
您应该致电lockObject.notifyAll()
。默认情况下,默认情况下直接调用notifyAll()
会调用此对象,但您确实没有实现Runnable接口的无效对象的监视器,因为您从未通过调用synchroized(this)
来执行此操作。这就是你获得例外的原因。
是。您应该使用Executor
,例如SingleThreadExecutor
和并发队列。除非您继续进行高性能计算,否则这是实现并发的强大而简单的方法。该套餐还提供了极好的功能和支持实用课程。查看java.util.concurrent
。
顺便说一下,你的包名包含大写字母,这是java编程规范不推荐的。
答案 1 :(得分:-1)
当我们同步任何块或方法时,我们应该同步类锁或对象锁。
但是你已经锁定了一些与该方法的调用者无关的对象
所以请将此更改从synchronized (lockObject)
更改为以下内容并运行
synchronized (this)