第一题
需求:根据示例数据完成如下功能
1. 统计每个用户的订单数量
2. 统计每个用户消费金额
3. 统计订单数量最多的用户
4. 统计消费金额最多的用户
5. 根据用户id统计该用户的订单
Order类
package com.mmg;
public class Order {
public String userId;
public String orderId;
public double amount;
public Order(String userId, String orderId, double amount) {
this.userId = userId;
this.orderId = orderId;
this.amount = amount;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
@Override
public String toString() {
return "Order{" +
"userId='" + userId + '\'' +
", orderId='" + orderId + '\'' +
", amount=" + amount +
'}';
}
}
SimpleTest
package com.mmg;
import java.util.*;
/**
* 需求:
* 1. 统计每个用户的订单数量
* 2. 统计每个用户消费金额
* 3. 统计订单数量最多的用户
* 4. 统计消费金额最多的用户
* 5. 根据用户id统计该用户的订单
*/
public class Test {
public static void main(String[] args) {
// 示例订单数据
List<Order> orders = Arrays.asList(
new Order("user1", "order1", 100),
new Order("user1", "order2", 200),
new Order("user2", "order3", 300),
new Order("user3", "order4", 100)
);
// 1. 统计每个用户的订单数量
Map<String, Integer> stringIntegerMap = countOrdersByUser(orders);
System.out.println(stringIntegerMap);
// 2. 统计每个用户消费金额
Map<String, Double> stringDoubleMap = sumAmountByUser(orders);
System.out.println(stringDoubleMap);
// 3. 统计订单数量最多的用户
String maxOrderUser = getMaxOrderUser(stringIntegerMap);
System.out.println("订单数量最多的用户: " + maxOrderUser);
// 4. 统计消费金额最多的用户
String maxAmountUser = getMaxAmountUser(stringDoubleMap);
System.out.println("消费金额最多的用户: " + maxAmountUser);
// 5. 根据用户id统计该用户的订单
List<Order> ordersByUserId = getOrdersByUserId(orders, "user1");
System.out.println(ordersByUserId);
}
// 1. 统计每个用户的订单数量
public static Map<String, Integer> countOrdersByUser(List<Order> orders) {
Map<String, Integer> countMap = new HashMap<>();
orders.forEach(order -> {
String userId = order.getUserId();
countMap.put(userId, countMap.getOrDefault(userId, 0) + 1);
});
return countMap;
}
// 2. 统计每个用户消费金额
public static Map<String, Double> sumAmountByUser(List<Order> orders) {
Map<String, Double> amountMap = new HashMap<>();
orders.forEach(order -> {
String userId = order.getUserId();
double amount = order.getAmount();
amountMap.put(userId, amountMap.getOrDefault(userId, 0.00) + amount);
});
return amountMap;
}
// 3. 统计订单数量最多的用户
public static String getMaxOrderUser(Map<String, Integer> countMap) {
String maxUser = null;
int maxCount = 0;
for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
if (entry.getValue() > maxCount) {
maxCount = entry.getValue();
maxUser = entry.getKey();
}
}
return maxUser;
}
// 4. 统计消费金额最多的用户
public static String getMaxAmountUser(Map<String, Double> amountMap) {
String maxUser = null;
double maxAmount = 0;
for (Map.Entry<String, Double> entry : amountMap.entrySet()) {
if (entry.getValue() > maxAmount) {
maxAmount = entry.getValue();
maxUser = entry.getKey();
}
}
return maxUser;
}
// 5. 根据用户id统计该用户的订单
public static List<Order> getOrdersByUserId(List<Order> orders, String userId) {
List<Order> orderList = new ArrayList<>();
orders.forEach(order -> {
if (userId.equals(order.getUserId())) {
orderList.add(order);
}
});
return orderList;
}
}
第二题
需求:使用多线程完成以下消费者-生产者案例
package com.mmg;
/**
* 生产者-消费者案例
*/
public class Test02 {
public static void main(String[] args) {
// 创建容量为10的仓库
Test02 warehouse = new Test02(10);
// 1. 生产者线程:每次生产3个面包,生产5次
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
int produceCount = 3;
warehouse.produceBread(produceCount);
System.out.println("【生产者】生产 " + produceCount + " 个面包,当前库存:" + warehouse.getCurrentStock());
Thread.sleep(500); // 模拟生产耗时
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("生产者线程被中断");
}
}, "生产者线程");
// 2. 消费者线程:每次消费2个面包,消费8次
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 8; i++) {
int consumeCount = 2;
warehouse.consumeBread(consumeCount);
System.out.println("【消费者】消费 " + consumeCount + " 个面包,当前库存:" + warehouse.getCurrentStock());
Thread.sleep(800); // 模拟消费耗时
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("消费者线程被中断");
}
}, "消费者线程");
// 启动线程
producer.start();
consumer.start();
}
private final int capacity; // 仓库容量(final修饰,初始化后不可变)
private int currentStock; // 当前库存(线程共享变量,需同步保护)
// 构造方法:初始化仓库容量和初始库存(初始库存为0)
public Test02(int capacity) {
this.capacity = capacity;
this.currentStock = 0;
}
/**
* 生产者方法:生产指定数量的面包
* @param count 生产数量(需大于0)
* @throws InterruptedException 线程等待被中断时抛出
*/
public synchronized void produceBread(int count) throws InterruptedException {
// 1. 合法性校验:生产数量不能为负数或0
if (count <= 0) {
throw new IllegalArgumentException("生产数量必须大于0!");
}
// 2. 等待仓库有足够空间(若当前库存+生产数量 > 容量,需等待)
// 用while而非if:防止线程被"虚假唤醒"(唤醒后需重新检查条件)
while (currentStock + count > capacity) {
System.out.println("【等待生产】当前库存:" + currentStock + ",生产" + count + "个后将超出容量" + capacity + ",等待消费者消费...");
this.wait(); // 释放锁,进入等待队列,直到被notifyAll()唤醒
}
// 3. 执行生产逻辑:更新当前库存
currentStock += count;
// 4. 唤醒等待的消费者(生产后库存增加,可能有消费者在等库存)
this.notifyAll();
}
/**
* 消费者方法:消费指定数量的面包
* @param count 消费数量(需大于0)
* @throws InterruptedException 线程等待被中断时抛出
*/
public synchronized void consumeBread(int count) throws InterruptedException {
// 1. 合法性校验:消费数量不能为负数或0
if (count <= 0) {
throw new IllegalArgumentException("消费数量必须大于0!");
}
// 2. 等待仓库有足够库存(若当前库存 < 消费数量,需等待)
while (currentStock < count) {
System.out.println("【等待消费】当前库存:" + currentStock + ",不足消费" + count + "个,等待生产者生产...");
this.wait(); // 释放锁,进入等待队列,直到被notifyAll()唤醒
}
// 3. 执行消费逻辑:更新当前库存
currentStock -= count;
// 4. 唤醒等待的生产者(消费后库存减少,可能有生产者在等空间)
this.notifyAll();
}
// 获取当前库存(同步方法,保证线程读取到最新值)
public synchronized int getCurrentStock() {
return currentStock;
}
// 获取仓库剩余空间(同步方法,保证计算基于最新库存)
public synchronized int getRemainingSpace() {
return capacity - currentStock;
}
}