6-4 多线程编程:使用多线程同步与通信,模拟实现售票系统的售票和退票过程。 (20 分)

使用synchronized实现同步控制,并使用wait()和notify()实现线程之间的通信。

编程要求如下:

可售出票的数量为一个固定值(total),从键盘读入。

当余票的数量足够出售时(余票数量大于客户购买票数),则先售票;如果没有余票了(票数为0)或余票数量不够了(余票数量小于客户购买票数),则需要等待退票。退票后,如果余票足够出售,则又开始售票。

退票规则:有票被售出,才能退票。如果退票数大于已售票总数,也只能退回已售出票的实际数量。比如:已售出3张票,第一次退回了2张票,第2次就只能退1张票了。

售票线程正在售票的时候不能退票,反之亦然。

程序包含以下类:

  1. 定义Ticket类(Tickets.java), 表示:票(能售或退)。
  2. 定义一个线程SellTicketThread类,售票线程,模拟多次(题中为3次)售票的操作;
  3. 定义一个线程ReturnTicketThread类,退票线程,模拟多次(题中为3次)退票的操作;
  4. 定义一个测试线程的主类Main.java,分别创建售票和退票的线程对象、启动线程,模拟多次售票和退票的过程。

需补充如下代码,使程序能正常运行:

  1. 为Ticket类补充sellTicket方法和returnTicket方法,两个方法均使用线程同步与通信实现,并将Ticket类补充完整。方法如下:
    synchronized public void sellTicket(int num); //num表示购票数,也就是售出票数
    synchronized public void returnTicket(int num); //num表示退票数

  2. 通过实现Runnable实现SellTicketThread类,编写SellTicketThread类。

  3. 通过实现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改了十来分钟,以后要更细心才行

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值