以下是一个可能的实现方案(使用Java语言):

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

enum UserType {
    PUBLIC, VIP, ORDINARY
}

class User {
    private final int number;
    private final UserType type;

    public User(int number, UserType type) {
        this.number = number;
        this.type = type;
    }

    public int getNumber() {
        return number;
    }

    public UserType getType() {
        return type;
    }
}

class Bank {
    private final int M;
    private final Queue<User> publicQueue;
    private final Queue<User> vipQueue;
    private final Queue<User> ordinaryQueue;
    private final Lock lock;
    private final Condition publicCond;
    private final Condition vipCond;
    private final Condition ordinaryCond;
    private int publicCounter;
    private int vipCounter;
    private int ordinaryCounter;

    public Bank(int M) {
        this.M = M;
        publicQueue = new LinkedList<>();
        vipQueue = new LinkedList<>();
        ordinaryQueue = new LinkedList<>();
        lock = new ReentrantLock();
        publicCond = lock.newCondition();
        vipCond = lock.newCondition();
        ordinaryCond = lock.newCondition();
        publicCounter = 0;
        vipCounter = 0;
        ordinaryCounter = 0;
    }

    public void takeNumber(User user) throws InterruptedException {
        lock.lock();
        try {
            switch (user.getType()) {
                case PUBLIC:
                    publicQueue.offer(user);
                    publicCond.signalAll();
                    break;
                case VIP:
                    vipQueue.offer(user);
                    vipCond.signalAll();
                    break;
                case ORDINARY:
                    ordinaryQueue.offer(user);
                    ordinaryCond.signalAll();
                    break;
            }
            System.out.println('User ' + user.getNumber() + ' (' + user.getType() + ') takes a number.');
        } finally {
            lock.unlock();
        }
    }

    public void serve() throws InterruptedException {
        lock.lock();
        try {
            while (true) {
                if (!publicQueue.isEmpty()) {
                    User user = publicQueue.poll();
                    System.out.println('Counter ' + (++publicCounter) + ' serves user ' + user.getNumber() + ' (' + user.getType() + ').');
                    Thread.sleep((long) (Math.random() * 1000)); // 模拟服务时间
                } else if (!vipQueue.isEmpty()) {
                    User user = vipQueue.poll();
                    System.out.println('Counter ' + (++vipCounter) + ' serves user ' + user.getNumber() + ' (' + user.getType() + ').');
                    Thread.sleep((long) (Math.random() * 1000));
                } else if (!ordinaryQueue.isEmpty()) {
                    User user = ordinaryQueue.poll();
                    System.out.println('Counter ' + (++ordinaryCounter) + ' serves user ' + user.getNumber() + ' (' + user.getType() + ').');
                    Thread.sleep((long) (Math.random() * 1000));
                } else {
                    if (publicCounter + vipCounter + ordinaryCounter >= M) {
                        System.out.println('All users have been served.');
                        return;
                    }
                    System.out.println('No user is waiting. Counters are idle.');
                    publicCond.await();
                    vipCond.await();
                    ordinaryCond.await();
                }
            }
        } finally {
            lock.unlock();
        }
    }
}

public class BankSystem {
    public static void main(String[] args) {
        Bank bank = new Bank(3);
        for (int i = 1; i <= 10; i++) {
            try {
                if (i % 3 == 0) {
                    bank.takeNumber(new User(i, UserType.PUBLIC));
                } else if (i % 4 == 0) {
                    bank.takeNumber(new User(i, UserType.VIP));
                } else {
                    bank.takeNumber(new User(i, UserType.ORDINARY));
                }
                Thread.sleep((long) (Math.random() * 1000)); // 模拟取号间隔时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            bank.serve();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这个实现方案中,银行类Bank有三个队列,分别存放对公用户、VIP用户和普通用户。takeNumber方法用于用户取号,将用户加入相应的队列中,并通知等待在相应条件上的服务员。serve方法用于服务员服务用户,按照优先级依次从三个队列中取出用户,并模拟服务时间。如果没有用户等待,则服务员等待在相应的条件上。当所有用户都被服务过后,服务员停止服务。

main方法中,模拟了10个用户依次取号的过程,并启动一个服务员线程对用户进行服务。可以看到,服务员按照优先级依次服务用户,而且每个用户只被服务一次。


原文地址: https://www.cveoy.top/t/topic/nSKl 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录