作業:
有一個水池,水池容量500L,一邊為進水口,一邊為出水口,要求進水放水不能同時進行,水池一旦滿了不能繼續注水,一旦空了,不能繼續放水,進水速度5L/s,放水速度2L/s。
這是我學多線程時做的一道練習題,剛開始對wait()方法存在錯誤理解導致運行時報異常-----java.lang.IllegalMonitorStateException,修復后,在此把錯誤寫法以及最終正確寫法都整理出來。
class Water{
static int litre = 500;
boolean flag=true; //false為可以繼續加水,true為可以繼續放水
}
class OutPour extends Thread{ //出水類
Water w;
OutPour(Water w){
this.w=w;
}
@Override
public void run() { //正確寫法
while(true){
synchronized(w){
if(w.flag==true){ //放水,2L/s
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
w.litre=w.litre-2;
System.out.println("放水中,現在還剩"+w.litre+"升水!");
if(w.litre<=0){ //放空了
w.flag=false;
System.out.println("--------空了!--------");
w.notify();
}
}else{
try {
w.wait();//等加滿
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/*
@Override
public void run() { //錯誤寫法
while(true){
if(w.flag==true){ //放水,2L/s
synchronized(w){
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
w.litre=w.litre-2;
System.out.println("放水中,現在還剩"+w.litre+"升水!");
if(w.litre<=0){ //放空了
w.flag=false;
System.out.println("--------空了!--------");
w.notify
}
}
}else{
try {
w.wait();//等加滿
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
*/
}
class InPour extends Thread{ //進水類
Water w;
InPour(Water w){
this.w=w;
}
@Override
public void run() { //正確寫法
while(true){
synchronized(w){
if(w.flag==false){//加水,5L/s
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
w.litre=w.litre+5;
System.out.println("加水中,現在有"+w.litre+"升水!");
if(w.litre>=500){//加滿了
System.out.println("-------滿了!-------");
w.flag=true;
w.notify();
}
}else{
try {
w.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/*
@Override
public void run() { //錯誤寫法
while(true){
if(w.flag==false){ //加水,5L/s
synchronized(w){
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
w.litre=w.litre+5;
if(w.litre>=500){ //加滿了
System.out.println("-------滿了!-------");
w.flag=true;
w.notifyAll();
}
}
}else{
try {
w.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
*/
}
public class Demo11 {
public static void main(String[] args){
Water w = new Water();
OutPour o = new OutPour(w);
InPour i = new InPour(w);
o.start();
i.start();
}
}
run方法在業務邏輯上並沒有錯,報異常java.lang.IllegalMonitorStateException,是因為wait()方法必須要放在同步代碼塊中才能使用。把else{}語句也圈到synchronized代碼塊即可。也奉勸,先把筆記看了之后再敲代碼,能為調試省不少時間。。。