三个线程模拟售票过程

superboboge 2014-09-26 12:34:54
代码:票类
public class Ticket {
private int ticketNum = 100;
public synchronized void sellTicket() {
ticketNum --;
}
public synchronized int getTicketNum() {
return ticketNum;
}

}


买票类:
public class BuyTicket implements Runnable {
private Ticket ticket;

public void setTicket(Ticket ticket) {
this.ticket = ticket;
}

@Override
public void run() {
while(ticket.getTicketNum()>0){
ticket.sellTicket();
System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.getTicketNum()+"张票" );

}
}

}


public class Main {
public static void main(String[] args) throws InterruptedException {
Ticket ticket = new Ticket();
BuyTicket buyTicket = new BuyTicket();
buyTicket.setTicket(ticket);
Thread Thread1 = new Thread(buyTicket,"窗口1");
Thread Thread2 = new Thread(buyTicket,"窗口2");
Thread Thread3 = new Thread(buyTicket,"窗口3");
Thread1.start();
Thread2.start();
Thread3.start();
}

}


运行结果第一次售票总是会有剩下两个98张 大家看看什么原因
...全文
1320 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lliiqiang 2014-09-30
  • 打赏
  • 举报
回复
这样肯定会有问题. 虽然买票过程同步了,但是获取票数信息的时候却和之前买票过程不同步,这个过程中会有其它线程改变票数,这个时候你得到的不是及时的你买完票之后的票数. public synchronized void sellTicket() { ticketNum --; System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticketNum+"张票" );//直接在买票方法里及时显示票数信息即可. }
dzq584462393 2014-09-29
  • 打赏
  • 举报
回复
看了下出错的原因,第一个线程卖票(减一个),卖票的过程确实别的进程进不来,但是你卖完后,你还等着输出剩余多少票的时候,下一个进程就又卖票了,然后你在输入,所以发生2张票同时卖出的效果
wopabe 2014-09-29
  • 打赏
  • 举报
回复
卖票过程没有错误,只是打印出来的信息欺骗了你,也就是说打印的不是卖的。 你这样改下: 先改下卖票方法
public synchronized int sellTicket() {
        ticketNum --;
        return ticketNum;
    }
然后改下run方法
while(ticket.getTicketNum()>0){
        System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.sellTicket()+"张票" );
        }
这样应该就可以了。 个人感觉查询票数的方法getTicketNum没必要定义为同步方法,因为在这个方法里没有修改ticketNum。
zhangzhizhenshuzu 2014-09-29
  • 打赏
  • 举报
回复
。。楼主不好意思。。刚才的代码还是会有点问题,同步代码块没把获取票数加进去,导致有线程先获取票数判断通过,再去买票。。导致票数结果又-1,-2.

这次的代码是终极版本。。调了半小时。。没问题了。。请参考。

public class SellTiketDemo {

public static void main(String[] args) {

Ticket ticket = new Ticket();
BuyTicket buyTicket = new BuyTicket();
buyTicket.setTicket(ticket);
new Thread(buyTicket,"窗口1").start();;
new Thread(buyTicket,"窗口2").start();;
new Thread(buyTicket,"窗口3").start();;
}

}

class Ticket {
private int ticketNum = 1000;

public void sellTicket() {
ticketNum--;

}


public int getTicketNum() {
return ticketNum;
}
}

class BuyTicket implements Runnable {
private Ticket ticket;

public void setTicket(Ticket ticket) {
this.ticket = ticket;
}

@Override
public void run() {
while(true){ //线程开始执行之后,先进入循环,再执行同步代码。这样避免了数据读写不同步的现象。
synchronized (ticket) {

if(ticket.getTicketNum()>0){
ticket.sellTicket();
System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.getTicketNum()+"张票" );
}
else {
break;
}
}
}
}
}


运行结果:

zhangzhizhenshuzu 2014-09-29
  • 打赏
  • 举报
回复
刚才运行了下,虽然共享数据不会出错了,貌似多线程的效率没体现出来,。 改了一下

public class SellTiketDemo {

    public static void main(String[] args) {
	
	        Ticket ticket = new Ticket();
	        BuyTicket buyTicket = new BuyTicket();
	        buyTicket.setTicket(ticket);
	        new Thread(buyTicket,"窗口1").start();;
	        new Thread(buyTicket,"窗口2").start();;
	        new Thread(buyTicket,"窗口3").start();;
    }

}

 class Ticket {
    private int ticketNum = 1000;
   Object lockObject=new Object();
 
   
       public  void sellTicket() {
	   synchronized (lockObject) {
	    ticketNum--;
	    System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+this.getTicketNum()+"张票" );
	}
	
        
    }
   
   
    public  int  getTicketNum() {
	synchronized (lockObject) {
	      return ticketNum;
	}
      
        
    }
     
}
 
 class BuyTicket implements Runnable {
     private Ticket ticket;
      
     public  void setTicket(Ticket ticket) {
         this.ticket = ticket;
     }
  
     @Override
     public  void run() {
	 
            while(ticket.getTicketNum()>0){
        	
             ticket.sellTicket();
  
            } 
         }
     
  
 }
zhangzhizhenshuzu 2014-09-29
  • 打赏
  • 举报
回复
楼主卖票本身没问题。只是打印顺序有问题,你的锁只有在sellTicket()方法内才有效。你想想,当一个线程执行完该方法,你的锁已经打开,这时候其他线程也可以卖票了。但是你的打印语句是在卖票方法之后再执行。。所以当然可能会出现打印的结果不是你期望的。 解决方法:将锁的位置加在线程实现代码里。打印语句直接放在卖票方法sellTicket()里。
public class SellTiketDemo { public static void main(String[] args) { Ticket ticket = new Ticket(); BuyTicket buyTicket = new BuyTicket(); buyTicket.setTicket(ticket); Thread Thread1 = new Thread(buyTicket,"窗口1"); Thread Thread2 = new Thread(buyTicket,"窗口2"); Thread Thread3 = new Thread(buyTicket,"窗口3"); Thread1.start(); Thread2.start(); Thread3.start(); } } class Ticket { private int ticketNum = 1000; public void sellTicket() { ticketNum--; System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+this.getTicketNum()+"张票" ); } public int getTicketNum() { return ticketNum; } } class BuyTicket implements Runnable { private Ticket ticket; public void setTicket(Ticket ticket) { this.ticket = ticket; } @Override public synchronized void run() { while(ticket.getTicketNum()>0){ ticket.sellTicket(); } } }
人_生而伟大 2014-09-29
  • 打赏
  • 举报
回复
你的run()方法也得是原子性的
binbinxyz 2014-09-28
  • 打赏
  • 举报
回复
在卖票和显示信息的过程中加上同步:
	while (ticket.getTicketNum() > 0) 
	{
		synchronized(ticket)
		{
			ticket.sellTicket();
			System.out.println(Thread.currentThread().getName()
					+ "卖了一张票,剩余" + ticket.getTicketNum() + "张票");
		}
	}
zyrobert 2014-09-26
  • 打赏
  • 举报
回复
很简单 sellticket和getticketnum两段代码之间发生了数值的修改 你应该将这两这方法 放在一个锁里面
Eniak 2014-09-26
  • 打赏
  • 举报
回复
使用java的关键,把变量锁住,或者使用线程安全的数组,如Vector等 或者添加关键字 volatile, synchronized 等
superboboge 2014-09-26
  • 打赏
  • 举报
回复
只有100张票三个窗口卖模拟这个过程
Coder_D 2014-09-26
  • 打赏
  • 举报
回复
新人问一个问题,楼主这样子写是每个窗口都有100张票还是三个窗口一共有100张票啊
superboboge 2014-09-26
  • 打赏
  • 举报
回复
有么有大神来看看怎么改啊
superboboge 2014-09-26
  • 打赏
  • 举报
回复
怎么操作呢?
毕业设计是高等教育阶段学生在完成学业前所进行的一项重要学术任务,旨在检验学生通过学习所获得的知识、技能以及对特定领域的深刻理解能力。这项任务通常要求学生运用所学专业知识,通过独立研究和创新,完成一个实际问题的解决方案或者开展一项有价值的项目。 首先,毕业设计的选择通常由学生根据个人兴趣、专业方向以及实际需求来确定。学生需要在导师的指导下明确研究目标、问题陈述,确立研究的范围和深度。毕业设计可以包括文献综述、需求分析、方案设计、实施与测试等多个阶段,以确保整个过程的科学性和系统性。 其次,毕业设计的完成通常需要学生具备一定的独立思考和解决问题的能力。在研究过程中,学生可能需要采用各种研究方法,如实验、调查、案例分析等,以获取必要的数据和信息。通过这些活动,学生能够培养扎实的专业技能,提升解决实际问题的实际能力。 第三,毕业设计的撰写是整个过程的重要组成部分。学生需要将研究过程、方法、结果以及结论等详细记录在毕业论文中,以展示其研究的全貌和成果。同时,撰写毕业设计还有助于提高学生的学术写作水平,培养清晰、逻辑的表达能力。 最后,毕业设计的评价通常由导师和相关专业人士进行。评价标准包括研究的创新性、实用性、方法的科学性以及论文的质量等方面。学生在毕业设计中获得的成绩也将直接影响其最终的学业成绩和学位授予。 总的来说,毕业设计是高等教育中的一项重要环节,通过此过程,学生不仅能够巩固所学知识,还能培养独立思考和解决问题的能力,为将来的职业发展奠定坚实的基础。
毕业设计是高等教育阶段学生在完成学业前所进行的一项重要学术任务,旨在检验学生通过学习所获得的知识、技能以及对特定领域的深刻理解能力。这项任务通常要求学生运用所学专业知识,通过独立研究和创新,完成一个实际问题的解决方案或者开展一项有价值的项目。 首先,毕业设计的选择通常由学生根据个人兴趣、专业方向以及实际需求来确定。学生需要在导师的指导下明确研究目标、问题陈述,确立研究的范围和深度。毕业设计可以包括文献综述、需求分析、方案设计、实施与测试等多个阶段,以确保整个过程的科学性和系统性。 其次,毕业设计的完成通常需要学生具备一定的独立思考和解决问题的能力。在研究过程中,学生可能需要采用各种研究方法,如实验、调查、案例分析等,以获取必要的数据和信息。通过这些活动,学生能够培养扎实的专业技能,提升解决实际问题的实际能力。 第三,毕业设计的撰写是整个过程的重要组成部分。学生需要将研究过程、方法、结果以及结论等详细记录在毕业论文中,以展示其研究的全貌和成果。同时,撰写毕业设计还有助于提高学生的学术写作水平,培养清晰、逻辑的表达能力。 最后,毕业设计的评价通常由导师和相关专业人士进行。评价标准包括研究的创新性、实用性、方法的科学性以及论文的质量等方面。学生在毕业设计中获得的成绩也将直接影响其最终的学业成绩和学位授予。 总的来说,毕业设计是高等教育中的一项重要环节,通过此过程,学生不仅能够巩固所学知识,还能培养独立思考和解决问题的能力,为将来的职业发展奠定坚实的基础。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧