楼主卖票本身没问题。只是打印顺序有问题,你的锁只有在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();
} }
}
刚才运行了下,虽然共享数据不会出错了,貌似多线程的效率没体现出来,。改了一下 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 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();
} }
}
。。楼主不好意思。。刚才的代码还是会有点问题,同步代码块没把获取票数加进去,导致有线程先获取票数判断通过,再去买票。。导致票数结果又-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) {
while (ticket.getTicketNum() > 0)
{
synchronized(ticket)
{
ticket.sellTicket();
System.out.println(Thread.currentThread().getName()
+ "卖了一张票,剩余" + ticket.getTicketNum() + "张票");
}
}
你这样改下:
先改下卖票方法
public synchronized int sellTicket() {
ticketNum --;
return ticketNum;
}
然后改下run方法
while(ticket.getTicketNum()>0){
System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.sellTicket()+"张票" );
}
这样应该就可以了。
个人感觉查询票数的方法getTicketNum没必要定义为同步方法,因为在这个方法里没有修改ticketNum。
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();
}
}
}
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();
}
}
}
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;
}
}
}
}
}
运行结果:
虽然买票过程同步了,但是获取票数信息的时候却和之前买票过程不同步,这个过程中会有其它线程改变票数,这个时候你得到的不是及时的你买完票之后的票数.
public synchronized void sellTicket() {
ticketNum --;
System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticketNum+"张票" );//直接在买票方法里及时显示票数信息即可.
}