java怎么做线程叫号看病

Java中,可以通过多线程模拟叫号看病系统,使用一个共享队列来存储排队的病人号码,一个加号线程定期向队列中添加号码,一个或多个叫号线程定期从队列中取出号码并模拟就诊

Java中实现线程叫号看病的模拟,可以通过多线程技术来模拟病人挂号、排队等待以及医生叫号看病的过程,下面将详细介绍如何实现这一过程,包括关键类的设计、线程的使用以及同步机制的应用。

java怎么做线程叫号看病

系统设计

整个叫号系统可以分为以下几个主要部分:

  • 病人类(Patient):表示每个病人,包含病人的编号、姓名等信息。
  • 挂号类(Registration):负责生成病人编号,并将病人加入候诊队列。
  • 候诊区类(WaitingRoom):使用队列数据结构管理等待看病的病人。
  • 医生类(Doctor):负责从候诊区中取出病人号码进行治疗。
  • 叫号机类(CallingMachine):模拟叫号的过程,按照一定的规则叫号。
  • 看病过程类(TreatmentProcess):模拟医生看病的过程,包括处理特需号和普通号的逻辑。

关键类的设计

1 病人类(Patient)

public class Patient {
    private int number;
    private String name;
    private boolean isSpecial; // 是否为特需号
    public Patient(int number, String name, boolean isSpecial) {
        this.number = number;
        this.name = name;
        this.isSpecial = isSpecial;
    }
    public int getNumber() {
        return number;
    }
    public String getName() {
        return name;
    }
    public boolean isSpecial() {
        return isSpecial;
    }
}

2 挂号类(Registration)

import java.util.concurrent.atomic.AtomicInteger;
public class Registration {
    private AtomicInteger atomicInteger;
    public Registration() {
        this.atomicInteger = new AtomicInteger(1);
    }
    public int generateNumber() {
        return atomicInteger.getAndIncrement();
    }
}

3 候诊区类(WaitingRoom)

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class WaitingRoom {
    private Queue<Patient> queue;
    public WaitingRoom(int capacity) {
        this.queue = new ArrayBlockingQueue<>(capacity);
    }
    public void addPatient(Patient patient) throws InterruptedException {
        queue.add(patient);
        System.out.println("Patient " + patient.getName() + " with number " + patient.getNumber() + " is waiting in the waiting room.");
    }
    public Patient getNextPatient() throws InterruptedException {
        Patient patient = queue.poll();
        if (patient != null) {
            System.out.println("Doctor is calling patient number: " + patient.getNumber() + ", Name: " + patient.getName());
        }
        return patient;
    }
}

4 医生类(Doctor)

public class Doctor implements Runnable {
    private WaitingRoom waitingRoom;
    private boolean isRunning;
    public Doctor(WaitingRoom waitingRoom) {
        this.waitingRoom = waitingRoom;
        this.isRunning = true;
    }
    @Override
    public void run() {
        while (isRunning) {
            try {
                Patient patient = waitingRoom.getNextPatient();
                if (patient != null) {
                    // 模拟看病时间
                    int treatmentTime = patient.isSpecial() ? 2000 : 1000; // 特需号看病时间是普通号的2倍
                    Thread.sleep(treatmentTime);
                    System.out.println("Finished treating patient number: " + patient.getNumber());
                } else {
                    // 如果没有病人,医生休息一会儿
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    public void stop() {
        isRunning = false;
    }
}

5 叫号机类(CallingMachine)

public class CallingMachine implements Runnable {
    private WaitingRoom waitingRoom;
    private Registration registration;
    private boolean isRunning;
    private int ordinaryCount = 0; // 普通号已叫号数量
    private int specialCount = 0; // 特需号已叫号数量
    private final int MAX_ORDINARY = 20; // 普通号总数
    private final int MAX_SPECIAL = 10; // 特需号总数
    public CallingMachine(WaitingRoom waitingRoom, Registration registration) {
        this.waitingRoom = waitingRoom;
        this.registration = registration;
        this.isRunning = true;
    }
    @Override
    public void run() {
        while (isRunning) {
            try {
                // 优先叫特需号,直到特需号叫完或者普通号叫到第10号
                if (specialCount < MAX_SPECIAL && (ordinaryCount < 10 || specialCount < MAX_SPECIAL)) {
                    int number = registration.generateNumber();
                    boolean isSpecial = number <= MAX_SPECIAL; // 假设前10个号为特需号
                    Patient patient = new Patient(number, "Patient" + number, isSpecial);
                    waitingRoom.addPatient(patient);
                    if (isSpecial) {
                        specialCount++;
                    } else {
                        ordinaryCount++;
                    }
                } else if (ordinaryCount < MAX_ORDINARY) {
                    // 普通号叫号,但需要先叫完特需号
                    int number = registration.generateNumber();
                    Patient patient = new Patient(number, "Patient" + number, false);
                    waitingRoom.addPatient(patient);
                    ordinaryCount++;
                } else {
                    // 所有号都已叫完,停止叫号
                    isRunning = false;
                }
                Thread.sleep(500); // 模拟叫号间隔
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    public void stop() {
        isRunning = false;
    }
}

6 医院类(Hospital)

public class Hospital {
    private WaitingRoom waitingRoom;
    private Registration registration;
    private Doctor doctor;
    private CallingMachine callingMachine;
    private Thread doctorThread;
    private Thread callingMachineThread;
    public Hospital(int waitingRoomCapacity) {
        this.waitingRoom = new WaitingRoom(waitingRoomCapacity);
        this.registration = new Registration();
        this.doctor = new Doctor(waitingRoom);
        this.callingMachine = new CallingMachine(waitingRoom, registration);
    }
    public void start() {
        doctorThread = new Thread(doctor);
        callingMachineThread = new Thread(callingMachine);
        doctorThread.start();
        callingMachineThread.start();
    }
    public void stop() {
        callingMachine.stop();
        doctor.stop();
        try {
            doctorThread.join();
            callingMachineThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    public static void main(String[] args) {
        Hospital hospital = new Hospital(30); // 候诊区容量为30
        hospital.start();
    }
}

同步机制与线程安全

在上述实现中,WaitingRoom类使用了ArrayBlockingQueue来保证线程安全,确保多个线程可以安全地添加和获取病人。Registration类使用了AtomicInteger来生成唯一的病人编号,避免了多线程环境下的竞争问题。DoctorCallingMachine类中的isRunning标志位用于控制线程的停止,确保在需要时可以安全地停止线程。

java怎么做线程叫号看病

运行效果与逻辑说明

运行程序后,可以看到挂号系统生成病人号码并加入候诊区,医生叫号后从候诊区取出病人号码,模拟了实际看病的流程,具体逻辑如下:

  1. 挂号与排队CallingMachine线程不断生成病人号码,并根据规则将病人加入候诊区,特需号优先于普通号,直到特需号叫完或者普通号叫到第10号,之后,继续叫普通号,直到所有号叫完。
  2. 医生叫号与看病Doctor线程不断从候诊区中取出病人号码,模拟看病过程,特需号的看病时间是普通号的2倍,医生在没有病人时会休息一会儿,避免空转。
  3. 线程停止:当所有号都叫完后,CallingMachine线程停止生成号码,Doctor线程在处理完所有病人后自动停止。Hospital类的stop方法确保所有线程都安全停止。

相关问答FAQs

Q1:如何确保特需号优先于普通号?

A1:在CallingMachine类中,通过判断当前已叫的特需号数量和普通号数量,优先生成特需号,直到特需号叫完或者普通号叫到第10号,这样可以确保特需号优先于普通号。

java怎么做线程叫号看病

Q2:如何处理医生在看病过程中的中断?

A2:在Doctor类的run方法中,使用try-catch块捕获InterruptedException异常,并在捕获到异常时调用Thread.currentThread().interrupt()方法,确保线程的中断状态被正确设置,这样,当外部调用stop方法时,医生

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/48556.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年7月8日 00:46
下一篇 2025年7月8日 00:49

相关推荐

  • Java jar包如何打开

    JAR包是Java的归档文件,通常通过命令行运行(如java -jar xxx.jar),若需查看内部文件,可使用解压软件(如WinRAR)直接解压或重命名为ZIP后解压。

    2025年6月28日
    100
  • Java如何实现301重定向?

    在Java中实现301重定向,需使用HttpServletResponse设置状态码为301并添加Location响应头,例如在Servlet中调用response.setStatus(301)和response.setHeader(“Location”, “目标URL”)即可完成永久重定向。

    2025年6月23日
    500
  • java怎么添加标签内容

    Java中,可以通过创建标签对象(如JLabel),使用setText()方法设置文本内容,再将其添加到容器(如JFrame)中来添加标签内容

    2025年7月8日
    000
  • Java计算器程序如何实现?

    Java计算器程序实现基础算术运算(加减乘除),支持用户通过图形界面或命令行输入表达式,程序包含异常处理机制,确保输入合法性验证(如除数非零),提供清晰结果输出,适合初学者理解基础逻辑与界面交互。

    2025年6月13日
    300
  • java下拉框怎么赋值

    Java中,为下拉框赋值的方法有多种,具体取决于所使用的GUI框架或Web技术,以下是几种常见的方法:,1. Swing中的JComboBox:通过addItem()方法添加选项,或在初始化时传入数组/Vector。,2. JavaFX中的ComboBox:使用ObservableList的add()方法动态添加选项,或通过setItems()初始化。,3. Web应用(HTML+Servlet):在HTML中使用`标签创建下拉框,通过Servlet动态生成并插入选项。,4. JSP/JSTL:结合Servlet传递数据,在JSP页面中使用`渲染选项。,5. 数据库驱动:从数据库获取数据后,通过DAO类查询并将结果集设置为下拉框的选项

    2025年7月8日
    000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN