工作队列(又名:任务队列)背后的主要思想是避免立即执行资源密集型任务而不得不等待它完成。相反,我们安排任务稍后完成。我们将任务封装 为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当您运行许多工人时,任务将在他们之间共享。
在上图 “P” 是我们的生产者,“C” 是我们的消费者。中间的盒子是一个队列——RabbitMQ 代表消费者保留的消息缓冲区。再工作队列中一个生产者有可能对应很多个消费者,消费者之间的关系是竞争关系。
使用 java 实现简单的消息队列模式
在简单消息队列中实现了生产者与消费者的代码,在工作队列的测试代码中只需要把消费者在复制出来一份即可。下面贴上实现的代码。
-
首先还是直接导入 Maven 坐标
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.9.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <!-- <scope>test</scope>--> </dependency>
-
创建第一个消费者(C)
public static void main(String[] args) { final Logger log = LoggerFactory.getLogger(Main.class); try { //创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); // 创建一个新的代理链接 Connection connection = factory.newConnection(); // 创建一个新的频道 Channel channel = connection.createChannel(); // 声明一个队列 channel.queueDeclare("work_queues_hello_world", true, false, false, null); DeliverCallback deliverCallback = (consumerTag, message) -> { String s = new String(message.getBody(), StandardCharsets.UTF_8); log.info("接收到来自生产者的消息:{}", s); try { // 让每此获取全都休息一秒钟 Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }; channel.basicConsume("work_queues_hello_world", true, deliverCallback, consumerTag -> { }); // 释放资源 // channel.close(); // connection.close(); } catch (Exception e) { e.printStackTrace(); } }
-
创建第二个消费者(C)
public static void main(String[] args) { final Logger log = LoggerFactory.getLogger(Main.class); try { //创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); // 创建一个新的代理链接 Connection connection = factory.newConnection(); // 创建一个新的频道 Channel channel = connection.createChannel(); // 声明一个队列 channel.queueDeclare("work_queues_hello_world", true, false, false, null); DeliverCallback deliverCallback = (consumerTag, message) -> { String s = new String(message.getBody(), StandardCharsets.UTF_8); log.info("接收到来自生产者的消息:{}", s); try { // 让每此获取全都休息一秒钟 Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }; channel.basicConsume("work_queues_hello_world", true, deliverCallback, consumerTag -> { }); // 释放资源 // channel.close(); // connection.close(); } catch (Exception e) { e.printStackTrace(); } }
-
创建一个生产者(P)用来发送消息
public static void main(String[] args) { final Logger log = LoggerFactory.getLogger(Main.class); try { //创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); // 创建一个新的代理链接 Connection connection = factory.newConnection(); // 创建一个新的频道 Channel channel = connection.createChannel(); // 声明一个队列 channel.queueDeclare("work_queues_hello_world", true, false, false, null); // 发送消息 for (int i = 1; i <= 10; i++) { StringBuilder stringBuilder = new StringBuilder(); String format = stringBuilder.append("发送消息: 你好这里是消息队列").append("发送时间: ").append(new Date()).append("发送次数: ").append(i).toString(); channel.basicPublish("", "work_queues_hello_world", null, format.getBytes(StandardCharsets.UTF_8)); log.info("发送成功,发送的消息为:{}", format); } // 释放资源 channel.close(); connection.close(); } catch (Exception e) { e.fillInStackTrace(); } }
-
启动生产者和消费者的服务
-
启动生产者
-
启动第一个消费者
-
启动第二个消费者
-