/**
* 本程序是模拟火车票售票
* 先存票再取票
*/
package Thread.App11_2;/**
* @WriteBy
* @E-mail [email protected]
* @date 2012-7-27
* @time 下午5:18:03
*/class Tickets {
private int size; // 设置票的总数
boolean available = false; // 标识当前是否有票可售 true代表有票可售
boolean stop = false; // 标识票是否售完 true表示票已售完
int num; public Tickets(int size) {
this.size = size;
} // 存票
public synchronized void put() {
if (available)
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("存入第" + (++num) + "张票!");
available = true;
notify();
} // 售票
public synchronized void sell() {
if (!available)
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("售出第" + num + "张票!");
if (num == size)
stop = true;
available = false;
notify();
}}// 存票机
class Producer extends Thread {
Tickets tickets = null; public Producer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.put();
}}// 售票机
class Consumer extends Thread {
Tickets tickets = null; public Consumer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.sell();
}
}public class APP11_2 { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets tickets = new Tickets(10);
new Producer(tickets).start();
new Consumer(tickets).start(); }}我运行的时候出现存入第1张票!
售出第1张票!
存入第2张票!
售出第2张票!
存入第3张票!
售出第3张票!
存入第4张票!
售出第4张票!
存入第5张票!
售出第5张票!
存入第6张票!
售出第6张票!
存入第7张票!
售出第7张票!
存入第8张票!
售出第8张票!
存入第9张票!
售出第9张票!
存入第10张票!
售出第10张票!
存入第11张票!
而调试的时候就不会出现最后的“存入第11张票 这是为什么
* 本程序是模拟火车票售票
* 先存票再取票
*/
package Thread.App11_2;/**
* @WriteBy
* @E-mail [email protected]
* @date 2012-7-27
* @time 下午5:18:03
*/class Tickets {
private int size; // 设置票的总数
boolean available = false; // 标识当前是否有票可售 true代表有票可售
boolean stop = false; // 标识票是否售完 true表示票已售完
int num; public Tickets(int size) {
this.size = size;
} // 存票
public synchronized void put() {
if (available)
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("存入第" + (++num) + "张票!");
available = true;
notify();
} // 售票
public synchronized void sell() {
if (!available)
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("售出第" + num + "张票!");
if (num == size)
stop = true;
available = false;
notify();
}}// 存票机
class Producer extends Thread {
Tickets tickets = null; public Producer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.put();
}}// 售票机
class Consumer extends Thread {
Tickets tickets = null; public Consumer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.sell();
}
}public class APP11_2 { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets tickets = new Tickets(10);
new Producer(tickets).start();
new Consumer(tickets).start(); }}我运行的时候出现存入第1张票!
售出第1张票!
存入第2张票!
售出第2张票!
存入第3张票!
售出第3张票!
存入第4张票!
售出第4张票!
存入第5张票!
售出第5张票!
存入第6张票!
售出第6张票!
存入第7张票!
售出第7张票!
存入第8张票!
售出第8张票!
存入第9张票!
售出第9张票!
存入第10张票!
售出第10张票!
存入第11张票!
而调试的时候就不会出现最后的“存入第11张票 这是为什么
运行时,程序连续运行,没有等待. 在存第10张票时,存入完,线程马上又判断stop==false为真,(此时,消费线程还没执行完,stop就是false. 生产线程又进入等待),等消费线程结束后,生产线程接着生产出第11个,再次循环判断stop==false,为假了,结束了。
而你调试用单步执行,生产完第10个后,线程没有马上判断 stop==false,而是等消费线程把第10个消费后,把stop赋值true后,再次执行生产线程,判断stop==false为假了,线程结束了。
2. 多线程间通信时,尽量使用 循环判断+notifyAll.而不是单次判断+ notify
1 在生产线程里把运行tickets.put()的条件改一下。
class Producer extends Thread {
Tickets tickets = null; public Producer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
//while (tickets.stop == false)
while(tickets.stop==false&&tickets.num<10) //num=10则不再出票了。
tickets.put();
}}
2 在put()方法里判断num如果大于10,则不输出了。
public synchronized void put() {
if (available)
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
++num; //改的地方
if(num<=10) //num大于10,不输出了。
{
System.out.println("存入第" + num + "张票!");
available = true;
notify();
}
}
private int size; // 设置票的总数
boolean available = false; // 标识当前是否有票可售 true代表有票可售
boolean stop = false; // 标识票是否售完 true表示票已售完
int num; public Tickets(int size) {
this.size = size;
} // 存票
public synchronized void put() {
if (available){
try {
wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}else{
System.out.println("存入第" + (++num) + "张票!");
available = true;
notify();
}
} // 售票
public synchronized void sell() {
if (!available){
try {
wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}else{
System.out.println("售出第" + num + "张票!");
if (num == size)
stop = true;
available = false;
notify();
}
}}// 存票机
class Producer extends Thread {
Tickets tickets = null; public Producer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.put();
}}// 售票机
class Consumer extends Thread {
Tickets tickets = null; public Consumer(Tickets tickets) {
this.tickets = tickets;
} public void run() {
while (tickets.stop == false)
tickets.sell();
}
}public class APP11_2 { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets tickets = new Tickets(10);
new Consumer(tickets).start();
new Producer(tickets).start(); }}
楼主看看行不?
建议改成public synchronized void put() {
while (available) // 这里if最好改成while
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("存入第" + (++num) + "张票!");
available = true;
notify();
}
// 售票
public synchronized void sell() {
if (!available) // 同理这里if也最好改成while
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("售出第" + num + "张票!");
if (num == size)
stop = true;
available = false;
notify();
}
if最好改成while,因为楼主是要靠available控制线程运行
7楼的办法可以,在if后面的语句和else后面的语句是分两次执行的。就是说执行if后面的语句,结束后,sell()或者put() 就结束了,run()方法继续判断条件tickets.stop == false,决定是否继续调用sell()或者put()方法。
等到生产线程的put()方法生产了10个后,消费线程还有执行完sell()方法,所以生产线程又进入了put()方法,但因为availble为true,所以进入了wait().
当消费线程sell()输出后,stop为true, notify()通知生产线程继续运行,此时if()结束。退出put()方法。线程再次判断tickets.stop == false时,已经为假,while()结束了。所以不再输出第11张票了。
前面几位说的很清楚了,输出11的问题在于第10张票还没取走,stop依旧false,这时produce的put方法开始了,但available为true,put就在等待,待到sell结束后,唤醒了put方法,从wait()继续往下执行。
if(){
wait();
}
A();//A存入第十一张票
if(){
wait();
}else{
A();
}
一个A执行,一个A不执行,这两段代码的区别应该很明白了吧
wait();
}
A();//存第十一张票if(){
wait
}else{
A();
}楼上的几位说的很清楚了。代码1 存票执行,代码2 不执行,这个楼主应该明白了吧