http://blog.csdn.net/zhu_tianwei/article/details/40887717

参考:http://blog.csdn.NET/lmj623565791/article/details/37620057

1.生产任务Task.Java

  1. package cn.slimsmart.rabbitmq.demo.workqueue;
  2. import com.rabbitmq.client.AMQP;
  3. import com.rabbitmq.client.Channel;
  4. import com.rabbitmq.client.Connection;
  5. import com.rabbitmq.client.ConnectionFactory;
  6. import com.rabbitmq.client.MessageProperties;
  7. public class Task {
  8. //队列名称
  9. private final static String QUEUE_NAME = "workqueue-durable";
  10. public static void main(String[] args) throws Exception {
  11. //创建连接和频道
  12. ConnectionFactory factory = new ConnectionFactory();
  13. factory.setHost("192.168.101.174");
  14. //指定用户 密码
  15. factory.setUsername("admin");
  16. factory.setPassword("admin");
  17. //指定端口
  18. factory.setPort(AMQP.PROTOCOL.PORT);
  19. Connection connection = factory.newConnection();
  20. Channel channel = connection.createChannel();
  21. boolean durable = true; //设置消息持久化  RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
  22. //声明队列
  23. channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
  24. //发送10条消息,依次在消息后面附加1-10个点
  25. for (int i = 5; i > 0; i--)
  26. {
  27. String dots = "";
  28. for (int j = 0; j <= i; j++)
  29. {
  30. dots += ".";
  31. }
  32. String message = "helloworld" + dots+dots.length();
  33. //MessageProperties.PERSISTENT_TEXT_PLAIN 标识我们的信息为持久化的
  34. channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
  35. System.out.println("Sent Message:'" + message + "'");
  36. }
  37. //关闭频道和资源
  38. channel.close();
  39. connection.close();
  40. }
  41. }

2.消费工作队列

  1. package cn.slimsmart.rabbitmq.demo.workqueue;
  2. import com.rabbitmq.client.AMQP;
  3. import com.rabbitmq.client.Channel;
  4. import com.rabbitmq.client.Connection;
  5. import com.rabbitmq.client.ConnectionFactory;
  6. import com.rabbitmq.client.QueueingConsumer;
  7. public class Work {
  8. //队列名称
  9. private final static String QUEUE_NAME = "workqueue-durable";
  10. public static void main(String[] args) throws Exception {
  11. //区分不同工作进程的输出
  12. int hashCode = Work.class.hashCode();
  13. //创建连接和频道
  14. ConnectionFactory factory = new ConnectionFactory();
  15. factory.setHost("192.168.101.174");
  16. //指定用户 密码
  17. factory.setUsername("admin");
  18. factory.setPassword("admin");
  19. //指定端口
  20. factory.setPort(AMQP.PROTOCOL.PORT);
  21. Connection connection = factory.newConnection();
  22. Channel channel = connection.createChannel();
  23. boolean durable = true; //设置消息持久化  RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
  24. //声明队列
  25. channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
  26. QueueingConsumer consumer = new QueueingConsumer(channel);
  27. /**
  28. * ack= true: Round-robin 转发   消费者被杀死,消息会丢失
  29. * ack=false:消息应答 ,为了保证消息永远不会丢失,RabbitMQ支持消息应答(message acknowledgments)。
  30. * 消费者发送应答给RabbitMQ,告诉它信息已经被接收和处理,然后RabbitMQ可以自由的进行信息删除。
  31. * 如果消费者被杀死而没有发送应答,RabbitMQ会认为该信息没有被完全的处理,然后将会重新转发给别的消费者。
  32. * 通过这种方式,你可以确认信息不会被丢失,即使消者偶尔被杀死。
  33. * 消费者需要耗费特别特别长的时间是允许的。
  34. *
  35. */
  36. boolean ack = false ; //打开应答机制
  37. // 指定消费队列
  38. channel.basicConsume(QUEUE_NAME, ack, consumer);
  39. //公平转发  设置最大服务转发消息数量    只有在消费者空闲的时候会发送下一条信息。
  40. int prefetchCount = 1;
  41. channel.basicQos(prefetchCount);
  42. while (true)
  43. {
  44. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  45. String message = new String(delivery.getBody());
  46. System.out.println(hashCode + " Received Message:'" + message + "'");
  47. doWork(message);
  48. System.out.println(hashCode + " Received Done");
  49. //发送应答
  50. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  51. }
  52. }
  53. /**
  54. * 每个点耗时1s
  55. * @param task
  56. * @throws InterruptedException
  57. */
  58. private static void doWork(String task) throws InterruptedException
  59. {
  60. for (char ch : task.toCharArray())
  61. {
  62. if (ch == '.')
  63. Thread.sleep(1000);
  64. }
  65. }
  66. }

多启动几个消费者工作进程,使用生产者发送消息,可以观察消费情况。

要了解RabbitMQ的路由机制,exchange是一个关键。exchange可以叫做交换机,也似乎可以叫做路由器,反正它是用来选择路由的。RabbitMQ的核心思想就是消息的发布者不是直接把消息发送到目标队列中的,事实上,通常它并不知道消息要发到哪个队列中,它只知道把消息队列发送到exchange中。exchange一边接收发送者发过来的消息,而另一边则把消息发送到目标队列中去。exchange一定知道哪些队列需要接收这个消息,是加到一个队列里还是加到好几个队列里,还是直接扔掉。

如果用空字符串去申明一个exchange,那么系统就会使用"amq.direct"这个exchange。前面我们使用的都是amq.direct类型。

channel.BasicPublish("", "TaskQueue", properties, bytes);

direct exchange 发送消息是要看routingKey的。举个例子,定义了一个direct exchange 名字是X1,然后一个queue名字为Q1 用routingKey=K1 绑定到exchange X1上,当一个routeKey为 K2 的消息到达X1上,那么只有K1=K2的时候,这个消息才能到达Q1上。

fanout类型的exchange就比较好理解。就是简单的广播,而且是忽略routingKey的。所以只要是有queue绑定到fanout exchange上,通过这个exchange发送的消息都会被发送到那些绑定的queue中,不管你有没有输入routingKey。

Topic类型的exchange给与我们更大的灵活性。通过定义routingKey可以有选择的订阅某些消息,此时routingKey就会是一个表达式。exchange会通过匹配绑定的routingKey来决定是否要把消息放入对应的队列中。有两种表达式符号可以让我们选择:#和*。

*(星号):代表任意的一个词。 例:*.a会匹配a.a,b.a,c.a等

#(井号):代码任意的0个或多个词。 例:#.a会匹配a.a,aa.a,aaa.a等

topic exchange 有时候的行为会像其他类型的exchange,比如说:

当routingKey只是有#号的时候,它的行为和fanout的行为是一样的。

当routingKey什么的没有,空字符串的时候,它的行为是和direct是一样的。

要注意的是,符号代表的是词不是字符。RabbitMQ中在表达式中词的定义是以.(点号)分隔的。

Headers类型的exchange使用的比较少。以后再说。

下面主要用代码,实现一下direct、fanout、topic的效果。

(转) RabbitMQ学习之工作队列(java)的更多相关文章

  1. RabbitMQ学习总结 第三篇:工作队列Work Queue

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  2. (转) RabbitMQ学习之远程过程调用(RPC)(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887885 在一般使用RabbitMQ做RPC很容易.客户端发送一个请求消息然后服务器回复一个响 ...

  3. (转)RabbitMQ学习之Headers交换类型(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40923131 Headers类型的exchange使用的比较少,它也是忽略routingKey的一 ...

  4. (转)RabbitMQ学习之主题topic(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...

  5. (转)RabbitMQ学习之路由(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887755 参考:http://blog.csdn.NET/lmj623565791/artic ...

  6. (转) RabbitMQ学习之发布/订阅(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887733 参考:http://blog.csdn.NET/lmj623565791/artic ...

  7. RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)

    1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...

  8. RabbitMQ学习总结 第二篇:快速入门HelloWorld

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  9. RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

随机推荐

  1. php第三节课

    正则表达式 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  2. 【Leetcode】【简单】【14最长公共前缀】【JavaScript】

    题目 14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower",& ...

  3. [luogu1073 Noip2009] 最优贸易 (dp || SPFA+分层图)

    传送门 Description C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分 为 ...

  4. c++ 打飞机游戏开发日志

    设计思路:控制台模式 初始化: 建立画面,初始化数据 游戏过程: 1.获取操作 2.修改数据 3.更新画面 结束: 关闭画面,delete动态分配数据 4.29日 创建游戏背景,实现飞机移动操作,实现 ...

  5. Oracle-表更名、转存数据

    --更名 ALTER TABLE T_LOGSRV_SERVICE RENAME TO T_LOGSRV_SERVICE_20170418_BAK; --创建同样的表 ;

  6. WIN7通过批处理开启/禁用无线网卡

    哥比較懒,直接上步骤: 1.看自己的电脑是否有devcon.exe 这个软件,能够直接在WINDOWS文件夹的SYSTEM32文件夹下面搜索.也能够通过命令行RUN-----------CMD---- ...

  7. oracle删除日志文件

    oracle删除日志文件 删除日志文件的语法例如以下: alter database drop logfile member logfile_name; 删除日志文件须要注意例如以下几点: 1.该日志 ...

  8. Android解决使用findViewById时须要对返回值进行类型转换问题的辅助类

    在我们的开发工作时,findViewById可能是用得最多的函数之中的一个.但它特别讨厌的地方就是我们常常须要对返回的view进行类型转换,输入麻烦.代码丑陋,比如曾经我们在Activity中找一些子 ...

  9. hdu4861 Couple doubi---2014 Multi-University Training Contest 1

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4861 Couple doubi Time Limit: 2000/1000 MS (Java/Othe ...

  10. Codeforces Round #253 (Div. 1)-A,B

    A题: 由题意可知,最多翻10次就能够(事实上8次就够了).那么我们就用状态压缩表示状态. 对于某种状态,假设某一位为0,那么代表这一位不翻,否则代表这一位翻. 对于某一种翻的状态: 假设牌中有G3, ...