Advanced Java Quiz 2 — Threads

发表于 2021-12-01 20:12 683 字 4 min read

cos avatar

cos

FE / ACG / 手工 / 深色模式强迫症 / INFP / 兴趣广泛养两只猫的老宅女 / remote

该文章设计并实现了火车票售票系统的放票与购票功能,通过多线程模拟服务器(Producer)每30分钟随机放出10张票,客户(Customer)每3分钟随机购买一张票,实现时间同步的售票过程。系统使用共享的Tickets类管理余票和时间,通过MyTime类控制时间流转,确保放票与购票在指定时间点有序进行。

This article has been machine-translated from Chinese. The translation may contain inaccuracies or awkward phrasing. If in doubt, please refer to the original Chinese version.

Problem

Design and implement the ticket release function for a train ticket system:

A certain train reserves 100 seated tickets, and starts releasing tickets at 8 PM every evening, randomly releasing 10 tickets every 30 minutes.

Simple simulation of ticket release and purchase: Display the customer who grabbed a certain ticket number at a certain time. Simulate server ticket release and client ticket purchase: The server displays information about which tickets were released at what time and which ticket was sold at what time; the client displays information about which ticket was purchased at what time.

Approach and Code

The server is the Producer class, the client is the Customer class, both extending Thread for multithreading. There is also a Tickets class representing remaining tickets and a MyTime class representing time.

Source code download: cos_javatest2

MyTime class: The passM function simulates the passage of minute minutes.

public class MyTime {
    int hour;
    int minute;
    public MyTime(int hour, int minute) {
        this.hour = hour%24;
        this.minute = minute%60;
    }
    public synchronized void printTime() {
        System.out.printf("%02d:%02d ", hour, minute);
    }
    public synchronized void passM(int minute) {
        this.minute += minute;
        if(this.minute >= 60) {
            ++this.hour;
            this.minute %= 60;
        }
        this.hour %= 24;
    }

    @Override
    public String toString() {
        return "MyTime{" +
                "hour=" + hour +
                ", minte=" + minute +
                '}';
    }
}

Tickets class:

This is the key part. total is the total number of reserved tickets (100), time is the current time, cid is the sales counter (1 means 1 ticket sold), pid is the stock counter (10 means 10 tickets stocked), available indicates whether tickets are available, serving as a synchronization flag. All are initialized to 0. The Tickets object is shared between the two threads.

import java.util.List;
import java.util.Stack;

public class Tickets {
    int total;          // Total tickets
    MyTime time;        // Current time
    int cid;            // Sales counter
    int pid;            // Stock counter
    boolean available;      // Whether tickets are available
    public Tickets(int total, MyTime time) {
        this.total = total;
        this.time = time;
        pid = cid = 0;
        available = false;
    }
    public synchronized void passM(int minute) {
        time.passM(minute);
    }
    public synchronized void put(int num) {  // Synchronized method to add tickets
        if(available) {
            System.out.println("Not time to stock tickets yet, please wait.");
            try {wait();} catch (InterruptedException e) {e.printStackTrace();}
        }
        pid += num;
        time.printTime();
        System.out.printf("Producer stocked %d tickets, current remaining: %d\n", num, pid-cid);
        available = true;
        notify();
    }
    public synchronized void sell() {  // Synchronized method to sell tickets
        if(!available) {
            System.out.printf("No tickets available, please wait @Customer %d\n", cid);
            try {wait();} catch (InterruptedException e) {e.printStackTrace();}
        }
        time.printTime();
        if(available && cid < pid) {
            System.out.printf("Customer %d purchased ticket %d\n", ++cid, cid);
        }
        if(cid == pid) available = false;
        notify();
    }
}

Customer class: Extends Thread with overridden run method. Assumes one customer buys a ticket every 3 minutes. Shares the Tickets object with the Producer class, so internal methods of Tickets must be synchronized.

public class Custormer extends Thread{
    Tickets t = null;
    Custormer(Tickets t) {
        this.t = t;
    }
    @Override
    public void run() {
        System.out.println("Custormer start");
        while(t.cid < t.total) {
            t.sell();
            t.passM(3);
            try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace();}
        }
        System.out.println("Custormer ends");
    }
}

Producer class:

public class Producer extends Thread {
    Tickets t = null;
    Producer(Tickets t) {
        this.t = t;
    }
    @Override
    public void run() {
        System.out.println("Producer start");
        while(t.pid < t.total) {
            t.put(10);
            try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace();}

        }
        System.out.println("Producer end");
    }
}

Main function: Creates two threads and starts them, setting the current time to 20

.

public class Main {
    public static void main(String[] args) {
        System.out.println("mainThread start");
        MyTime time = new MyTime(20, 0);
        time.printTime();
        System.out.println(" Current time");
        Tickets tickets = new Tickets(100, time);
        Producer pthread = new Producer(tickets);
        Custormer cthread = new Custormer(tickets);
        pthread.start();
        cthread.start();
        System.out.println("mainThread end");
    }
}

Execution Results

The execution results are shown in the figures below:

Result 1
Result 2
Result 3

喜欢的话,留下你的评论吧~

© 2020 - 2026 cos @cosine
Powered by theme astro-koharu · Inspired by Shoka