实现一个银行系统该银行设置有M个窗口。每个用户需要先取号只有一台取号机。用户分为对公用户私人用户。私人用户又分为普通用户VIP用户。其中窗口的柜员在服务时按优先级给用户服务其中对公用户的优先级最高VIP用户次之普通用户优先级最低。请使用同步与互斥解决此银行的叫号服务系统。
以下是一个可能的实现方案(使用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/eyO6 著作权归作者所有。请勿转载和采集!