Java并发编程(四):多线程带来的性能飞跃
多线程带来的性能飞跃
- 1 概述
- 2 程序示例及分析
- 2.1 示例
- 2.2 示例程序分析
- 3 总结
大家好,我是欧阳方超,微信公众号同名。
1 概述
本文通过一个订单处理示例,演示一下使用多线程后可以带来显著的性能提升。
2 程序示例及分析
2.1 示例
模拟数据库库存
public class Inventory {
//模拟数据库库存
private final Object lock = new Object();
private int stock = 1000;//初始库存1000
public boolean deduct(int amount) {
synchronized (lock) {
if (stock >= amount) {
//模拟数据库延迟操作
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
stock -= amount;
return true;
}
return false;
}
}
public int getStock() {
synchronized (lock) {
return stock;
}
}
}
模拟订单类
//订单类
class Order {
private final int orderId;
private final int quantity;
private boolean isProcessed;
public Order(int orderId, int quantity) {
this.orderId = orderId;
this.quantity = quantity;
this.isProcessed = false;
}
public int getQuantity() {
return quantity;
}
public void setIsProcessed(boolean isProcessed) {
this.isProcessed = isProcessed;
}
@Override
public String toString() {
return "Order{" +
"orderId=" + orderId +
", quantity=" + quantity +
", isProcessed=" + isProcessed +
'}';
}
}
订单处理器
class OrderProcessor {
private final Inventory inventory;
private final AtomicInteger successCount = new AtomicInteger(0);
private final AtomicInteger failureCount = new AtomicInteger(0);
public OrderProcessor(Inventory inventory) {
this.inventory = inventory;
}
public void process(Order order) {
//模拟订单验证(无需加锁的耗时操作)
validateOrder(order);
//模拟订单价格计算(无需加锁的耗时操作)
calculatePrice(order);
//扣减库存(需要加锁的操作)
boolean success = inventory.deduct(order.getQuantity());
if (success) {
//模拟发送确认操作邮件(无需加锁的耗时操作)
sendConfirmationEmail(order);
order.setIsProcessed(true);
//order.isProcessed = true;
successCount.incrementAndGet();
} else {
failureCount.incrementAndGet();
}
}
public void validateOrder(Order order) {
try {
//模拟耗时的验证过程
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void calculatePrice(Order order) {
try {
//模拟耗时的价格计算
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void sendConfirmationEmail(Order order) {
try {
//模拟耗时的发送邮件操作
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public int getSuccessCount() {
return successCount.get();
}
public int getFailureCount() {
return failureCount.get();
}
}
主方法所在类
public class OrderProcessingDemo {
public static void main(String[] args) throws InterruptedException {
//创建订单列表
List<Order> orders = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 100; i++) {//创建100个订单
//orders.add(new Order(i, random.nextInt(5) + 1));//每个订单购买1-5件商品
orders.add(new Order(i, 5));//每个订单购买5件商品
}
Inventory inventory = new Inventory();
OrderProcessor processor = new OrderProcessor(inventory);
//单线程处理
long startTime = System.currentTimeMillis();
for (Order order : orders) {
processor.process(order);
}
long singleThreadTime = System.currentTimeMillis() - startTime;
//重置库存和处理器
inventory = new Inventory();
processor = new OrderProcessor(inventory);
//多线程处理
startTime = System.currentTimeMillis();
ExecutorService executorService = Executors.newFixedThreadPool(20);
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (Order order : orders) {
OrderProcessor finalProcessor = processor;
CompletableFuture<Void> future = CompletableFuture.runAsync(
() -> finalProcessor.process(order), executorService
);
futures.add(future);
}
//等待所有订单处理完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executorService.shutdown();
long multiThreadTime = System.currentTimeMillis() - startTime;
// 打印结果
System.out.println("单线程处理时间: " + singleThreadTime + "ms");
System.out.println("多线程处理时间: " + multiThreadTime + "ms");
System.out.println("性能提升: " + String.format("%.2f", (float) singleThreadTime / multiThreadTime) + "倍");
System.out.println("成功处理订单数: " + processor.getSuccessCount());
System.out.println("失败订单数: " + processor.getFailureCount());
System.out.println("剩余库存: " + inventory.getStock());
}
}
程序运行结果:
单线程处理时间: 34163ms
多线程处理时间: 2030ms
性能提升: 16.83倍
成功处理订单数: 100
失败订单数: 0
剩余库存: 500
2.2 示例程序分析
- Inventory类
这个类模拟了一个库存管理系统。
lock成员变量是用于同步库存操作的锁对象。
dedect(int amount)方法尝试从库存中扣减指定数量的商品,使用synchronized关键词来确保线程安全。 - Order类
这是一个订单类,没有太多与多线程相关的内容。 - OrderProcessor类
这个类负责处理订单,并与库存进行交互。
- 成员变量:inventory: 引用一个 Inventory 对象,用于库存管理。successCount 和 failureCount: 使用 AtomicInteger 来统计成功和失败的订单数,以保证在多线程环境下的线程安全。
- 方法:process(Order order):验证订单(模拟耗时操作)。计算价格(模拟耗时操作)。尝试从库存中扣减请求的商品数量。如果成功,发送确认邮件并更新订单状态;如果失败,增加失败计数。validateOrder(Order order), calculatePrice(Order order), 和 sendConfirmationEmail(Order order):这些方法模拟了验证、价格计算和发送确认邮件的耗时操作。
- OrderProcessingDemo类
这是程序的主类,负责执行整个订单处理流程。
- main方法:创建一个包含100个订单的列表,每个订单有5件商品。创建一个Inventory对象和一个对应的OrderProcessor对象。单线程处理,使用单线程循环遍历所有订单并调用处理器进行处理,记录处理时间。多线程处理重置库存和处理器后,使用一个固定大小为20的线程池来并发处理所有订单。每个订单通过CompletableFuture.runAsync()方法异步处理,并将结果存储在一个列表中。使用CompletableFuture.allOf()等待所有异步任务完成,然后关闭线程池。输出结果
最后程序打印单线程和多线程处理所需时间、性能提升倍数、成功和失败的订单数量以及剩余库存量。
3 总结
本文通过一个订单处理的示例,演示了使用多线程能够带来显著的性能飞跃。在实际项目中,通过将任务分解为多个并行执行的线程,能够更好地利用多核处理器的优势,提高系统并发处理能力。
上一篇:JVM GC排查-JFR