工作队列(任务队列)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务。
我们通过一个简单的demo来看一下多线程下是如何处理这些任务队列的。
工作线程(消费者)
public class Worker01 {
// 队列名称
public static final String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
// 建立连接创建信道工具类,详细代码在上一篇文章
Channel channel = RabbitMqUtils.getChannel();
DeliverCallback deliverCallback = (consumerTag,message)->{
System.out.println("接收到的消息"+new String (message.getBody()));
};
// 取消接收消息回调
CancelCallback cancelCallback = consumerTag->{
System.out.println(consumerTag+"消息者取消消费接口回调逻辑");
};
System.out.println("01等待接收消息.........");
// 消息的接收
channel.basicConsume(QUEUE_NAME,true,deliverCallback,cancelCallback);
}
}
在idea里面我i们可以启动两次Worker01,实现模拟两个工作线程,开启方式根据idea版本不同稍有差异
版本一:
版本二:
勾选完毕后记得apply->ok
启动后
生产者发送大量消息
生产者采用scanner扫描器,实现控制台输入发送消息
public class Task01 {
public static final String QUEUE_NAME = "hello";
// 发送大量消息
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtils.getChannel();
/**
* 生成队列
*1.队列名称
*2.队列里面的消息是否进行持久化(磁盘) 默认情况消息存储在内存中
*3.该队列是否只提供一个消费者进行消费 是否进行消息的共享 true可以多个消费者消费
*4.是否自动删除 最后一个消费者开连接以后 该队列是否自动删除 true自动删除
*5.其他参数 延迟 死信等
*/
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String message = scanner.next();
/**
* 发送一个消息
* 1.发送到哪个交换机
* 2.路由的key值是哪一个 本次是队列名称
* 3.其他参数信息
* 4.发送消息的消息体
*
* */
channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
System.out.println("消息已发送"+message);
}
}
}
现在进行测试,我们已经启动了两个worker,现在启动一下task,并输入1, 2, 3, 4
可以看到多个线程在处理一个工作队列时采用的是轮询消息消费。