使用synchronized实现同步控制,并使用wait()和notify()实现线程之间的通信。
编程要求如下:
可售出票的数量为一个固定值(total),从键盘读入。 当余票的数量足够出售时(余票数量大于客户购买票数),则先售票;如果没有余票了(票数为0)或余票数量不够了(余票数量小于客户购买票数),则需要等待退票。退票后,如果余票足够出售,则又开始售票。 退票规则:有票被售出,才能退票。如果退票数大于已售票总数,也只能退回已售出票的实际数量。比如:已售出3张票,第一次退回了2张票,第2次就只能退1张票了。 售票线程正在售票的时候不能退票,反之亦然。
程序包含以下类:
- 定义Ticket类(Tickets.java), 表示:票(能售或退)。
- 定义一个线程SellTicketThread类,售票线程,模拟多次(题中为3次)售票的操作;
- 定义一个线程ReturnTicketThread类,退票线程,模拟多次(题中为3次)退票的操作;
- 定义一个测试线程的主类Main.java,分别创建售票和退票的线程对象、启动线程,模拟多次售票和退票的过程。
需补充如下代码,使程序能正常运行:
为Ticket类补充sellTicket方法和returnTicket方法,两个方法均使用线程同步与通信实现,并将Ticket类补充完整。方法如下:
synchronized public void sellTicket(int num); //num表示购票数,也就是售出票数
synchronized public void returnTicket(int num); //num表示退票数通过实现Runnable实现SellTicketThread类,编写SellTicketThread类。
通过实现Runnable实现ReturnTicketThread类,编写ReturnTicketThread类。
答案:
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws InterruptedException {
Scanner sc=new Scanner(System.in);
//System.out.println("请输入票数:");
int num=sc.nextInt(); //从键盘读入总票数
Ticket tickets = new Ticket(num); //产生票
new Thread(new sellTicketThread(tickets)).start();//sellTicketThread售票
new Thread(new returnTicketThread(tickets)).start();//returnTicketThread退票
Thread.sleep(50); //休眠等待售票和退票执行完毕
System.out.println(tickets.freeNum);
}
}
class Ticket {
int total; //总票数
int freeNum; //多线程共享变量:余票数量
int soldNum; //已售出票数
boolean hasTicket; //true表示有足够的票出售,false则表示票数不够
int count = 3; //线程售票退票次数
int sellNum = 3; //单次售票数量
int returnNum = 2; //单次退票数量
public Ticket(int number) {
total = number;
freeNum = total; //售票前:总数与余票数相等
soldNum = 0; //已售出票数
hasTicket = (freeNum >= sellNum); //余票足够
}
//上面是裁判程序,下面是答案
//在下面补充Ticket类的synchronized售票方法
synchronized public void sellTicket(int num){//num表示购票数,也就是售出票数
while (freeNum < sellNum){
//System.out.println("余票不足");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
freeNum-=num;
soldNum+=num;
System.out.println("售出"+num+"余票"+freeNum);
notifyAll();
}
//在下面补充Ticket类的synchronized退票方法,并将Ticket类补充完整
synchronized public void returnTicket(int num){//num表示退票数
while(returnNum > soldNum || freeNum >= sellNum){//优先售票
//System.out.println("补票过多");
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
freeNum+=num;
soldNum-=num;
System.out.println("退回"+num+"余票"+freeNum);
notifyAll();
}
}
//在下面补充SellTicketThread类,通过实现Runnable实现SellTicketThread类
class sellTicketThread implements Runnable{
Ticket tickets;
public sellTicketThread() {
}
public sellTicketThread(Ticket tickets){
this.tickets = tickets;
}
@Override
public void run() {
for(int i=0;i<tickets.count;i++)
tickets.sellTicket(tickets.sellNum);
}
}
//在下面补充ReturnTicketThread类,通过实现Runnable实现ReturnTicketThread类
class returnTicketThread implements Runnable{
Ticket tickets;
public returnTicketThread(){}
public returnTicketThread(Ticket tickets){
this.tickets = tickets;
}
@Override
public void run() {
for(int i=0;i<tickets.count;i++)
tickets.returnTicket(tickets.returnNum);
}
}
总结,简单生产者消费者模式的多线程题目,写的时候吧sellNum打成了soldNum改了十来分钟,以后要更细心才行