java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java秒杀系统

基于Java设计一个高并发的秒杀系统

作者:orton777

这篇文章主要为大家详细介绍了如何基于Java设计一个高并发的秒杀系统,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考下

设计一个高并发的Java秒杀系统需要考虑以下几个方面:

一、下面是一个简单的Java秒杀系统的示例代码:

// 商品实体类
public class Product {
    private String id;
    private String name;
    private int stock;

    // 省略构造方法和Getter/Setter
}

// 秒杀订单实体类
public class Order {
    private String id;
    private String productId;
    private String userId;
    private Date createTime;

    // 省略构造方法和Getter/Setter
}

// 秒杀服务类
@Service
public class SeckillService {
    private static final int MAX_STOCK = 100; // 商品的最大库存数量

    private final Map<String, Product> products = new ConcurrentHashMap<>(); // 商品信息
    private final Set<String> seckillUsers = new HashSet<>(); // 已秒杀用户

    @PostConstruct
    public void init() {
        // 初始化商品信息
        Product product = new Product("1", "iPhone 12", MAX_STOCK);
        products.put(product.getId(), product);
    }

    // 执行秒杀操作
    public synchronized boolean seckill(String productId, String userId) {
        // 判断商品是否存在
        Product product = products.get(productId);
        if (product == null) {
            return false;
        }

        // 判断商品库存是否足够
        if (product.getStock() <= 0) {
            return false;
        }

        // 判断用户是否已经秒杀过
        if (seckillUsers.contains(userId)) {
            return false;
        }

        // 执行秒杀逻辑
        product.setStock(product.getStock() - 1);
        Order order = new Order(UUID.randomUUID().toString(), productId, userId, new Date());
        // 保存订单信息到数据库或消息队列等
        // ...

        // 添加已秒杀用户
        seckillUsers.add(userId);

        return true;
    }
}

// 秒杀控制器
@RestController
public class SeckillController {
    private final SeckillService seckillService;

    public SeckillController(SeckillService seckillService) {
        this.seckillService = seckillService;
    }

    @PostMapping("/seckill")
    public String seckill(@RequestParam("productId") String productId,
                          @RequestParam("userId") String userId) {
        boolean success = seckillService.seckill(productId, userId);
        if (success) {
            return "秒杀成功";
        } else {
            return "秒杀失败";
        }
    }
}

这个示例中,秒杀系统使用了一个内存中的Map来保存商品信息,使用了一个Set来保存已经秒杀过的用户。在秒杀操作中,通过加锁来保证秒杀的原子性。

二、以下是一个使用RabbitMQ设计的Java秒杀系统的生产者和消费者的代码示例:

生产者代码示例:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

public class SeckillProducer {

    private static final String QUEUE_NAME = "seckillQueue";

    public static void main(String[] args) throws IOException, TimeoutException {
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");

        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);

            // 模拟秒杀请求
            String productId = "12345";
            String userId = UUID.randomUUID().toString();

            // 发送秒杀消息到队列
            String message = productId + "," + userId;
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
            System.out.println("秒杀消息发送成功:" + message);
        }
    }
}

消费者代码示例:

import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class SeckillConsumer {

    private static final String QUEUE_NAME = "seckillQueue";

    public static void main(String[] args) throws IOException, TimeoutException {
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");

        // 创建连接
        Connection connection = factory.newConnection();

        // 创建通道
        Channel channel = connection.createChannel();

        // 声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        // 创建消费者
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("收到秒杀消息:" + message);

                // 处理秒杀逻辑
                processSeckillMessage(message);

                // 手动确认消息已被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };

        // 监听队列并消费消息
        channel.basicConsume(QUEUE_NAME, false, consumer);
    }

    private static void processSeckillMessage(String message) {
        // 解析消息,执行秒杀逻辑
        String[] parts = message.split(",");
        String productId = parts[0];
        String userId = parts[1];

        // 执行秒杀操作
        // ...
    }
}

在这个示例中,我们使用RabbitMQ作为消息队列来处理秒杀请求。生产者通过RabbitMQ的Java客户端库创建连接和通道,然后声明一个队列,并发送秒杀消息到队列中。

消费者也通过RabbitMQ的Java客户端库创建连接和通道,然后声明同样的队列,并创建一个消费者来监听队列并消费消息。当消费者接收到秒杀消息后,会调用processSeckillMessage方法来处理秒杀逻辑,并手动确认消息已被消费。

这只是一个简单的示例,实际的秒杀系统中可能还需要考虑消息持久化、消息重试机制、并发控制等问题。

到此这篇关于基于Java设计一个高并发的秒杀系统的文章就介绍到这了,更多相关Java秒杀系统内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文