今晚在csdn上乱逛,随便点了一些推荐的帖子,看到一个模拟多人售票的程序,然后看了下各位高手的作答,再自己动手写了下。总算完工,但是出现了些莫名的错误,找了很久也没找到问题!现将代码贴上,各位帮忙指出错误!/**
* @(#)SellTicket.java
*
*
* @author
* @version 1.00 2010/8/21
*/class SellLady{
int tickCount,five,ten ; //票数,5元零钞,10元零钞
static int Priority = 10 ; //设置线程优先级,越早等待值越大
public SellLady(int count,int five,int ten){
this.tickCount = count ;
this.five = five ;
this.ten = ten ;
}
public synchronized static int getPriority(){
SellLady.Priority--;
if(SellLady.Priority <0)
SellLady.Priority = 0 ;
return SellLady.Priority;
}
public synchronized String sell(int num ,int money){
String msg = "" ;
if(tickCount <= 0)
return "对不起,票已售完,明天请早!" ;
else if(money == 5){
tickCount--;
five++;
msg = "给你票,你的钱正好,不用找零!" +five;
notifyAll();
}else if(money ==10){
while(five < 1){
try {
System.out.println("" + num + "号顾客用10元购票,请等待 " +five);
// Thread.currentThread().setPriority(SellLady.getPriority()) ;
wait(); } catch (InterruptedException e) {} }
//二次判断
if(tickCount <= 0) return "对不起,票已售完,明天请早!" ;
tickCount--;
five--;
ten++;
msg = "给你票,找你5元。" +five;
}
return msg ;
}
}class Buyer implements Runnable{
int num ,money ;
public Buyer(int n,int m){
this.num = n ;
this.money = m;
} public void run(){
// synchronized(this){
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
// }
}
}
public class SellTicket { public SellTicket() {
} static SellLady sl = new SellLady(14,0,0);
public static void main (String[] args) { Buyer[] by = new Buyer[14] ; //14位顾客,对应14张票
int[] money ={ 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10}; //对应14位顾客买票的币值
Thread[] t = new Thread[14] ;
for(int i=0;i<by.length;i++){
by[i] = new Buyer(i+1,money[i]);
t[i] = new Thread(by[i]) ;
t[i].start();
} for (int i = 0; i < by.length; i++) {
try {
t[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("票已售完" +sl.tickCount);
}}
再附上某次的运行结果:
1号顾客用10元购票,请等待 0
我是3号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是2号顾客,用10元钱买票,售票员说:给你票,找你5元。0
4号顾客用10元购票,请等待 0
我是5号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是4号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是7号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是6号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票氲却?0
1号顾客用10元购票,请等待 0
我是8号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
9号顾客用10元购票,请等待 0
我是1号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是10号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是11号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票,请等待 0
我是9号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是12号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是13号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是14号顾客,用10元钱买票,售票员说:给你票,找你5元。0
票已售完0
-----------------------------------------------------------------
一些说明:
程序里有14个进程,模拟14个顾客买票,对应有个数组存放买票的币值。若是5元,还剩票,直接可以买;若是10元,还剩票,则需要有5元零钞才可以买!
* @(#)SellTicket.java
*
*
* @author
* @version 1.00 2010/8/21
*/class SellLady{
int tickCount,five,ten ; //票数,5元零钞,10元零钞
static int Priority = 10 ; //设置线程优先级,越早等待值越大
public SellLady(int count,int five,int ten){
this.tickCount = count ;
this.five = five ;
this.ten = ten ;
}
public synchronized static int getPriority(){
SellLady.Priority--;
if(SellLady.Priority <0)
SellLady.Priority = 0 ;
return SellLady.Priority;
}
public synchronized String sell(int num ,int money){
String msg = "" ;
if(tickCount <= 0)
return "对不起,票已售完,明天请早!" ;
else if(money == 5){
tickCount--;
five++;
msg = "给你票,你的钱正好,不用找零!" +five;
notifyAll();
}else if(money ==10){
while(five < 1){
try {
System.out.println("" + num + "号顾客用10元购票,请等待 " +five);
// Thread.currentThread().setPriority(SellLady.getPriority()) ;
wait(); } catch (InterruptedException e) {} }
//二次判断
if(tickCount <= 0) return "对不起,票已售完,明天请早!" ;
tickCount--;
five--;
ten++;
msg = "给你票,找你5元。" +five;
}
return msg ;
}
}class Buyer implements Runnable{
int num ,money ;
public Buyer(int n,int m){
this.num = n ;
this.money = m;
} public void run(){
// synchronized(this){
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
// }
}
}
public class SellTicket { public SellTicket() {
} static SellLady sl = new SellLady(14,0,0);
public static void main (String[] args) { Buyer[] by = new Buyer[14] ; //14位顾客,对应14张票
int[] money ={ 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10}; //对应14位顾客买票的币值
Thread[] t = new Thread[14] ;
for(int i=0;i<by.length;i++){
by[i] = new Buyer(i+1,money[i]);
t[i] = new Thread(by[i]) ;
t[i].start();
} for (int i = 0; i < by.length; i++) {
try {
t[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("票已售完" +sl.tickCount);
}}
再附上某次的运行结果:
1号顾客用10元购票,请等待 0
我是3号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是2号顾客,用10元钱买票,售票员说:给你票,找你5元。0
4号顾客用10元购票,请等待 0
我是5号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是4号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是7号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是6号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票氲却?0
1号顾客用10元购票,请等待 0
我是8号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
9号顾客用10元购票,请等待 0
我是1号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是10号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是11号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票,请等待 0
我是9号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是12号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是13号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是14号顾客,用10元钱买票,售票员说:给你票,找你5元。0
票已售完0
-----------------------------------------------------------------
一些说明:
程序里有14个进程,模拟14个顾客买票,对应有个数组存放买票的币值。若是5元,还剩票,直接可以买;若是10元,还剩票,则需要有5元零钞才可以买!
String msg = "" ;
if(tickCount <= 0)
return "对不起,票已售完,明天请早!" ;
else if(money == 5){
tickCount--;
five++;
msg = "给你票,你的钱正好,不用找零!" +five;
notifyAll();
}else if(money ==10){
while(five < 1){
try {
System.out.println("" + num + "号顾客用10元购票,请等待 " +five);
// Thread.currentThread().setPriority(SellLady.getPriority()) ;
wait(); } catch (InterruptedException e) {} }
//二次判断
上面红色的你换成 ++five; 试一下
试了,还是不行~~~~~~~~~
另外说下,那个乱码应该是和环境有关!因为我是在JC下运行的,运行多几次就会出现乱码了。但是我转到cmd下去运行,无论运行多少次都不会出现乱码~~~~~
在这里 five++ 和 ++five 都一样,因为five值都会自增1。
只有在赋值给其他变量的时候,这2者才会有不同。比如:
b = five++ ;
b = ++five ;
第一种是先赋值再运算。结果b=five
第二种是先运算再赋值,结果是b=five+1 ;
当复习了~~~~~~
如果所有打印都放在同步块内,就没有问题了附带修改后的代码/**
* @(#)SellTicket.java
* @author
* @version 1.00 2010/8/21
*/class SellLady {
int tickCount, five, ten; // 票数,5元零钞,10元零钞
static int Priority = 10; // 设置线程优先级,越早等待值越大 public SellLady(int count, int five, int ten) {
this.tickCount = count;
this.five = five;
this.ten = ten;
} public synchronized static int getPriority() {
SellLady.Priority--;
if (SellLady.Priority < 0)
SellLady.Priority = 0;
return SellLady.Priority;
} private void println(String s) {
Buyer b = (Buyer) Thread.currentThread();
System.out.println("售票员:你好," + b.num + "号顾客," + s);
} public synchronized void sell(int num, int money) {
System.out.println(num + "号顾客:用" + money + "元买票");
if (tickCount <= 0) {
println("对不起,票已售完,明天请早!");
return;
} else if (money == 5) {
tickCount--;
five++;
println("给你票,你的钱正好,不用找零!");
System.out.println("售票员:5元零钞还有" + five + "张");
notifyAll();
} else if (money == 10) {
if (five < 1)
println("无5元零钞,请等待!");
while (five < 1) {
System.out.println(num + "号顾客:我等....");
try {
wait();
} catch (InterruptedException ie) {
break;
}
}
// 二次判断
if (tickCount <= 0)
println("对不起,票已售完,明天请早!");
else {
tickCount--;
five--;
ten++;
println("给你票,找你5元。");
System.out.println("售票员:5元零钞还有" + five + "张");
}
}
}
}class Buyer extends Thread {
int num, money; public Buyer(int n, int m) {
this.num = n;
this.money = m;
} public void run() {
SellTicket.sl.sell(num, money);
}
}public class SellTicket { public SellTicket() {
} static SellLady sl = new SellLady(14, 0, 0); public static void main(String[] args) {
Buyer[] by = new Buyer[14]; // 14位顾客,对应14张票
int[] money = { 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10 }; // 对应14位顾客买票的币值
for (int i = 0; i < by.length; i++) {
by[i] = new Buyer(i + 1, money[i]);
by[i].start();
} for (int i = 0; i < by.length; i++) {
try {
by[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("票已售完" + sl.tickCount);
}
}
为什么直接打印出来就会顺序紊乱,而你修改后的代码也就是加了个打印的方法,但是这个方法都没使用synchronized,为什么酒不会顺序紊乱呢?!请指点,谢谢
把打印操作都放在了同步的方法里面,就没问题了!
但是我之前测试的时候,
把下面的2行注释去掉,也是打印混乱,难道我加的synchronized没有用?!请教原因...
public void run(){
// synchronized(this){
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
// }
谢谢不厌其烦的指点,谢谢~~~~~~~~~
int tickCount,five,ten ; //票数,5元零钞,10元零钞
public SellLady(int count,int five,int ten){
this.tickCount = count ;
this.five = five ;
this.ten = ten ;
}
public synchronized void sell(int num ,int money) {
if(tickCount <= 0) {
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:对不起,票已售完,明天请早!!("+five+")") ;
}
else if(money == 5){
tickCount--;
five++;
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:给你票,你的钱正好,不用找零!!("+five+")") ;
notifyAll();
}else if(money ==10){
while(five < 1){
try {
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:当前无法找退,请等待!!("+five+")") ;
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//二次判断
if(tickCount <= 0) {
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:对不起,票已售完,明天请早!!("+five+")");
}
tickCount--;
five--;
ten++;
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:给你票,找你5元!!("+five+")");
}
}
}
class Buyer implements Runnable{
int num ,money ;
public Buyer(int n,int m){
this.num = n ;
this.money = m;
} public void run(){
SellTicket.sl.sell(num,money);
}
}
public class SellTicket {
static SellLady sl = new SellLady(14,0,0);
public static void main (String[] args) {
Buyer[] by = new Buyer[14] ; //14位顾客,对应14张票
int[] money ={ 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10}; //对应14位顾客买票的币值
Thread[] t = new Thread[14] ;
for(int i=0;i<by.length;i++){
by[i] = new Buyer(i+1,money[i]);
t[i] = new Thread(by[i]) ;
t[i].start();
}
}
}测试结果:(每次执行的结果很有可能不一样,但都能保证刚好每人都可以买到一张)我是1号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是3号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
我是1号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
我是5号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
我是4号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
我是6号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是2号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是9号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是7号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
我是9号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
我是2号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是6号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
我是10号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
我是8号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(2)
我是6号顾客,用10元钱买票,售票员说:给你票,找你5元!!(1)
我是2号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
我是13号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
我是12号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(2)
我是14号顾客,用10元钱买票,售票员说:给你票,找你5元!!(1)
我是11号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
首先,程序逻辑什么的是没错的!之所以出现打印紊乱的原因在于:在
class Buyer implements Runnable{
int num ,money ;
public Buyer(int n,int m){
this.num = n ;
this.money = m;
} public void run(){
// synchronized(this){
System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
// }
}
}
在这个类里面我做了打印的操作。试想下,假如我同时启动了14个线程的话,那么我将无法确保打印的顺序!所以解决方法就是将打印的操作都放到同步方法sell里面,这样就能确保打印不会出现紊乱。感谢大家的指点。共同学习,共同进步!