生產消費者問題是經典的問題
我有一個箱子,可以放蘋果,有一個生產者生產蘋果,一個消費者消費蘋果,用線程可以這樣寫:
/*箱子*/
class PT {
private String info="蘋果";
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
/*生產者*/
class MyThread9 implements Runnable {
private PT pt;
public MyThread9(PT pt) {
this.pt = pt;
}
@Override
public void run() {
for(int i = 0; i<10; i++) {
System.out.println("生產:蘋果");
pt.setInfo("蘋果");
}
}
}
/*消費者*/
class MyThread10 implements Runnable {
private PT pt;
public MyThread10(PT pt) {
this.pt = pt;
}
@Override
public void run() {
for(int i = 0; i<10; i++) {
System.out.println("消費:" + pt.getInfo());
}
}
}
public class test5 {
public static void main(String ar[]) {
PT pt = new PT();
MyThread9 m = new MyThread9(pt);
MyThread10 m1 = new MyThread10(pt);
Thread t1 = new Thread(m,"生產者");
Thread t2 = new Thread(m1,"消費者");
t1.start();
t2.start();
}
}
而這樣的結果,會出問題,如果我的箱子只能放一個蘋果,那麼就只有
箱子爲空,生產者才能放蘋果,
箱子不爲空,消費者才能取蘋果
而程序運行的結果:
會出現一直放,或者一直取,這樣明顯不符合邏輯。
要解決這個問題,需要用到Object類的方法:
例子:
/*箱子*/
class PT {
private String info="蘋果";
/*箱子爲空的標記*/
private boolean flag = false;
public synchronized void get() {
if(flag) {
/*箱子爲空,當前線程等待,等到箱子不爲空時會被喚醒*/
try {
super.wait();
} catch(Exception e) {e.printStackTrace();}
} else {
/*箱子不爲空,取走蘋果*/
System.out.println("消費:"+info);
/*標記箱子爲空*/
flag = true;
/*喚醒線程*/
super.notify();
}
}
public synchronized void setInfo(String info) {
if(!flag) {
/*如果箱子不爲空,則生產者線程等待,等待箱子爲空的時候會被喚醒*/
try {
super.wait();
} catch(Exception e){e.printStackTrace();}
}
else {
/*箱子爲空,可以生產*/
this.info = info;
System.out.println("生產:蘋果");
/*標記箱子不爲空*/
flag = false;
/*喚醒等待的線程*/
super.notify();
}
}
}
/*生產者*/
class MyThread9 implements Runnable {
private PT pt;
public MyThread9(PT pt) {
this.pt = pt;
}
@Override
public void run() {
for(int i = 0; i<10; i++) {
pt.setInfo("蘋果");
}
}
}
/*消費者*/
class MyThread10 implements Runnable {
private PT pt;
public MyThread10(PT pt) {
this.pt = pt;
}
@Override
public void run() {
for(int i = 0; i<10; i++) {
pt.get();
}
}
}
public class test5 {
public static void main(String ar[]) {
PT pt = new PT();
MyThread9 m = new MyThread9(pt);
MyThread10 m1 = new MyThread10(pt);
Thread t1 = new Thread(m,"生產者");
Thread t2 = new Thread(m1,"消費者");
t2.start();
t1.start();
}
}
結果:
這樣就能解決生產者消費者問題
至於notify()與notifyAll()的區別,你可以理解爲,
notify()是有序的喚醒,
notifyAll()是無序的喚醒,喚醒後誰的優先級高,誰就更有可能先執行。