关于线程的锁的一个问题
///////////////////Airport.java
import java.awt.*;
import java.io.*;
import java.util.*;
/**
* @author elove
*
*/
public class Airport {
public AirportMap airportMap;
protected ThreadGroup tg;
private static Vector <Plane> runwayList=new Vector <Plane> ();//#2
private static Vector <Plane> gatesList=new Vector <Plane> ();//#1
public Airport(){
Frame mapFrame;
Panel pl;
mapFrame=new Frame( "Airport Map ");
airportMap=new AirportMap();
pl=new Panel();
pl.setLayout(new BorderLayout());
pl.add( "Center ", airportMap);
mapFrame.add( "Center ", pl);
mapFrame.setSize(200, 300);
mapFrame.pack();
tg= new ThreadGroup( "Threads ");
// Old
/*
*
Plane planes[]=new Plane[1];
planes[0]=new Plane(tg,0,this);
try{
planes[0].join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.exit(0);*/
// New
Plane planes[]=new Plane[2];
for(int j=0;j <2;j++){
planes[j]=new Plane(tg,j,this);
}
synchronized(this){
try{
wait(5000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.exit(0);
}
private void RequestLock(Plane pl,Vector <Plane> locklist){
boolean empty;
synchronized(locklist){
empty=locklist.isEmpty();
locklist.addElement(pl);
}
if(empty==false){
try{
pl.wait();
}
catch(InterruptedException e){e.printStackTrace();}
}
}
public void ReleaseLock(Plane pl,Vector <Plane> lockList){
Plane peek;// To notify a plane!
synchronized(lockList){
lockList.removeElement(pl);
if (lockList.isEmpty()==false){
try{
peek=lockList.firstElement();
synchronized(peek){
peek.notify();
}
}catch(NoSuchElementException e){
e.printStackTrace();
}
}
}
}
public void RequestRunwayLock(Plane pl){
RequestLock(pl,runwayList);
}
public void RequestGatesLock(Plane pl){
RequestLock(pl,gatesList);
}
public void ReleaseRunwayLock(Plane pl){
ReleaseLock(pl,runwayList);
System.out.println(pl.threadName+ "ReleaseGatesLock ");
}
public void ReleaseGatesLock(Plane pl){
ReleaseLock(pl,gatesList);
System.out.println(pl.threadName+ "ReleaseRunwayLock ");
}
public static void main(String[] args){
System.out.println( "Ok ");
new Airport();
System.out.println( "Ok ");
}
}
--------------------------------
///////////////////////AirportMap.java
import java.awt.*;
public class AirportMap extends Canvas{
/**
*
*/
private static final long serialVersionUID = 1L;
public void LandPlane(Plane pl){
}
public void TaxiToGate(Plane pl){
}
public void Takeoff(Plane pl){
}
}
------------------------------------
////////////////Plane.java
import java.awt.*;
import java.io.*;
import java.util.*;
public class Plane extends Thread{
String threadName;
Airport airport;
static int timeAtGate;
public Plane(ThreadGroup tg,int name,Airport theAirport){
super(tg, "Plane- "+name);
airport=theAirport;
timeAtGate=3000;
threadName=new String( "Plane- "+name);
this.start();
}
public void createImages(){
}
public void run(){
System.out.println( "Waiting to land "+threadName);
/* #2 */
airport.RequestRunwayLock(this);
System.out.println( "Got use of runway "+threadName);
System.out.println( "Landing "+threadName);
airport.airportMap.LandPlane(this);
System.out.println( "Landed "+threadName);
/* #3 */
airport.ReleaseRunwayLock(this);
/* #1 */
airport.RequestGatesLock(this);
System.out.println( "Got a gate "+threadName);
airport.airportMap.TaxiToGate(this);
System.out.println( "At gate "+threadName);
/* Spend some time at the gate! */
try{
sleep(timeAtGate);
}catch(InterruptedException e){e.printStackTrace();}
airport.RequestRunwayLock(this);
System.out.println( "Got runway for takeoff "+threadName);
airport.airportMap.Takeoff(this);
airport.ReleaseGatesLock(this);
airport.ReleaseRunwayLock(this);
System.out.println( "END "+threadName);
}
}
=====================================================================================================================================================
编译结果:
Ok
Waiting to land Plane-0
Got use of runway Plane-0
Landing Plane-0
Landed Plane-0
Plane-0ReleaseGatesLock
Got a gate Plane-0
At gate Plane-0
Waiting to land Plane-1
Got use of runway Plane-1
Landing Plane-1
Landed Plane-1
Plane-1ReleaseGatesLock
Exception in thread "Plane-1 " java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:474)
at Airport.RequestLock(Airport.java:75)
at Airport.RequestGatesLock(Airport.java:104)
at Plane.run(Plane.java:40)
Got runway for takeoffPlane-0
Plane-0ReleaseRunwayLock
Plane-0ReleaseGatesLock
ENDPlane-0
---------------------------------------------
不知道到底是什么原因报这个错误呀,怎么解决呢?
[解决办法]
调用wait()方法时,要先获得锁
如
synchronized (lock){
wait();
}
注:wait()和notify()要用一个锁,调用notify()也要先获得锁
[解决办法]
在airport这个对象里 不要执行其他对象的wait,只能执行自己的wait
不然会说你不是owner
如果飞机场的各种资源需要互斥,那么应该让airport调用wait 而不是plane,因为是在使用飞机场的资源上出现冲突,而不是飞机出现冲突
[解决办法]
在AirPort类的RequestLock方法里,wait()方法没有获取对象锁,所以抛出异常,我改了
import java.awt.*;
import java.io.*;
import java.util.*;
/**
* @author elove
*
*/
public class Airport {
public AirportMap airportMap;
protected ThreadGroup tg;
private static Vector <Plane> runwayList=new Vector <Plane> ();//#2
private static Vector <Plane> gatesList=new Vector <Plane> ();//#1
public Airport(){
Frame mapFrame;
Panel pl;
mapFrame=new Frame( "Airport Map ");
airportMap=new AirportMap();
pl=new Panel();
pl.setLayout(new BorderLayout());
pl.add( "Center ", airportMap);
mapFrame.add( "Center ", pl);
mapFrame.setSize(200, 300);
mapFrame.pack();
tg= new ThreadGroup( "Threads ");
// Old
/*
*
Plane planes[]=new Plane[1];
planes[0]=new Plane(tg,0,this);
try{
planes[0].join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.exit(0);*/
// New
Plane planes[]=new Plane[2];
for(int j=0;j <2;j++){
planes[j]=new Plane(tg,j,this);
}
synchronized(this){
try{
wait(5000);
}catch(InterruptedException e){
e.printStackTrace();
}//catch
}//synchronized
//System.exit(0);
}
private void RequestLock(Plane pl,Vector <Plane> locklist){
boolean empty;
synchronized(locklist){
empty=locklist.isEmpty();
locklist.addElement(pl);
}
if(empty==false){
try{
synchronized(pl){
pl.wait();}
}
catch(InterruptedException e){e.printStackTrace();}
}
}
public void ReleaseLock(Plane pl,Vector <Plane> lockList){
Plane peek;// To notify a plane!
synchronized(lockList){
lockList.removeElement(pl);
if (lockList.isEmpty()==false){
try{
peek=lockList.firstElement();
synchronized(peek){
peek.notify();
}
}catch(NoSuchElementException e){
e.printStackTrace();
}
}
}
}
public void RequestRunwayLock(Plane pl){
RequestLock(pl,runwayList);
}
public void RequestGatesLock(Plane pl){
RequestLock(pl,gatesList);
}
public void ReleaseRunwayLock(Plane pl){
ReleaseLock(pl,runwayList);
System.out.println(pl.threadName+ " ReleaseGatesLock ");
}
public void ReleaseGatesLock(Plane pl){
ReleaseLock(pl,gatesList);
System.out.println(pl.threadName+ "ReleaseRunwayLock ");
}
public static void main(String[] args){
System.out.println( "Ok ");
new Airport();
System.out.println( "Ok ");
}
}
这样第一个Plane就可以结束,但是第二个没有结束似乎在等待别人的唤醒,你看看有没帮助吧