Redis: Jedis 源代码剖析2- 发布者/订阅者模式剖析
来源:互联网 发布:淘宝联盟手机app 编辑:程序博客网 时间:2024/05/18 15:56
在Jedis提供的发布者/订阅者模式中,最重要的就是JedisPubSub . 当订阅通道后,JedisPubSub就会轮询通道。直到通道取消订阅,才会继续执行。
因为Jedis是单线程,所以当订阅之后,线程就在循环。除非,在JedisPubSub收到消息后,新开线程继续执行任务。
在JedisPubSub 类中定义了接受消息后触发事件和轮询代码。JedisPubSub类是抽象类,所以为了实现自己的功能,必须继承该类。
public abstract class JedisPubSub { private int subscribedChannels = 0; private volatile Client client; public void onMessage(String channel, String message) { } public void onPMessage(String pattern, String channel, String message) { } public void onSubscribe(String channel, int subscribedChannels) { } public void onUnsubscribe(String channel, int subscribedChannels) { } public void onPUnsubscribe(String pattern, int subscribedChannels) { } public void onPSubscribe(String pattern, int subscribedChannels) { } public void unsubscribe() { if (client == null) { throw new JedisConnectionException("JedisPubSub was not subscribed to a Jedis instance."); } client.unsubscribe(); client.flush(); } public void unsubscribe(String... channels) { if (client == null) { throw new JedisConnectionException("JedisPubSub is not subscribed to a Jedis instance."); } client.unsubscribe(channels); client.flush(); } public void subscribe(String... channels) { if (client == null) { throw new JedisConnectionException("JedisPubSub is not subscribed to a Jedis instance."); } client.subscribe(channels); client.flush(); } public void psubscribe(String... patterns) { if (client == null) { throw new JedisConnectionException("JedisPubSub is not subscribed to a Jedis instance."); } client.psubscribe(patterns); client.flush(); } public void punsubscribe() { if (client == null) { throw new JedisConnectionException("JedisPubSub is not subscribed to a Jedis instance."); } client.punsubscribe(); client.flush(); } public void punsubscribe(String... patterns) { if (client == null) { throw new JedisConnectionException("JedisPubSub is not subscribed to a Jedis instance."); } client.punsubscribe(patterns); client.flush(); } public boolean isSubscribed() { return subscribedChannels > 0; } public void proceedWithPatterns(Client client, String... patterns) { this.client = client; client.psubscribe(patterns); client.flush(); process(client); } public void proceed(Client client, String... channels) { this.client = client; client.subscribe(channels); client.flush(); process(client); } //JedisPubSub执行一直轮询,直到取消订阅。 private void process(Client client) { do { List<Object> reply = client.getRawObjectMultiBulkReply(); final Object firstObj = reply.get(0); if (!(firstObj instanceof byte[])) { throw new JedisException("Unknown message type: " + firstObj); } final byte[] resp = (byte[]) firstObj; if (Arrays.equals(SUBSCRIBE.raw, resp)) { subscribedChannels = ((Long) reply.get(2)).intValue(); final byte[] bchannel = (byte[]) reply.get(1); final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); onSubscribe(strchannel, subscribedChannels); } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { subscribedChannels = ((Long) reply.get(2)).intValue(); final byte[] bchannel = (byte[]) reply.get(1); final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); onUnsubscribe(strchannel, subscribedChannels); } else if (Arrays.equals(MESSAGE.raw, resp)) { final byte[] bchannel = (byte[]) reply.get(1); final byte[] bmesg = (byte[]) reply.get(2); final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); onMessage(strchannel, strmesg); } else if (Arrays.equals(PMESSAGE.raw, resp)) { final byte[] bpattern = (byte[]) reply.get(1); final byte[] bchannel = (byte[]) reply.get(2); final byte[] bmesg = (byte[]) reply.get(3); final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); onPMessage(strpattern, strchannel, strmesg); } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { subscribedChannels = ((Long) reply.get(2)).intValue(); final byte[] bpattern = (byte[]) reply.get(1); final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); onPSubscribe(strpattern, subscribedChannels); } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { subscribedChannels = ((Long) reply.get(2)).intValue(); final byte[] bpattern = (byte[]) reply.get(1); final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); onPUnsubscribe(strpattern, subscribedChannels); } else { throw new JedisException("Unknown message type: " + firstObj); } } while (isSubscribed()); /* Invalidate instance since this thread is no longer listening */ this.client = null; } public int getSubscribedChannels() { return subscribedChannels; }}
/** * Note that subscribe is a blocking operation because it will poll Redis for responses on the thread that calls subscribe. * A single JedisPubSub instance can be used to subscribe to multiple channels. * You can call subscribe or psubscribe on an existing JedisPubSub instance to change your subscriptions. * @author Administrator * */public class JedisPubSubListener extends JedisPubSub{@Overridepublic void onMessage(String channel, String message) {super.onMessage(channel, message);System.out.println("onMessage");}@Overridepublic void onPMessage(String pattern, String channel, String message) {// TODO Auto-generated method stubsuper.onPMessage(pattern, channel, message);System.out.println("onPMessage");}@Overridepublic void onSubscribe(String channel, int subscribedChannels) {// TODO Auto-generated method stubsuper.onSubscribe(channel, subscribedChannels);System.out.println("onSubscribe");}@Overridepublic void onUnsubscribe(String channel, int subscribedChannels) {// TODO Auto-generated method stubsuper.onUnsubscribe(channel, subscribedChannels);System.out.println("onUnsubscribe");}@Overridepublic void onPUnsubscribe(String pattern, int subscribedChannels) {// TODO Auto-generated method stubsuper.onPUnsubscribe(pattern, subscribedChannels);System.out.println("onPUnsubscribe");}@Overridepublic void onPSubscribe(String pattern, int subscribedChannels) {// TODO Auto-generated method stubsuper.onPSubscribe(pattern, subscribedChannels);System.out.println("onPSubscribe");}}
TestPub 为测试类,一直发布消息:
public class TestPub {public static void main(String[] args) {Jedis jedis = new Jedis();while (true) { try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} jedis.publish("channel", "Pub_Message");}}}
TestSub消息进行订阅:
public class TestSub {
public static void main(String[] args)
{
Jedis jedis =new Jedis();
//创建一个订阅者
JedisPubSub listener =new JedisPubSubListener();
//订阅指定通道
jedis.subscribe(listener, "channel");
System.out.println("===subscribe success==");
}
}
1 0
- Redis: Jedis 源代码剖析2- 发布者/订阅者模式剖析
- 发布者订阅者模式
- Redis: Jedis 源代码剖析1-链接建立和收发命令
- Redis:redission 源代码剖析3 future模式
- Step into Redis- 07 - 发布者-订阅者
- Redis 学习笔记十 发布者订阅者模式与生产者消费者模式
- 发布者订阅者模式(一)
- 简单的订阅者/发布者模式
- javascript 观察者模式 (订阅者与发布者)
- 一个订阅发布者模式
- 订阅/发布者模式---JavaScript
- activemq发布者/订阅模式模式
- 发布者&订阅者模型
- Python——redis发布者/订阅者笔记
- Qt C++ Observer模式(发布者-订阅者)
- ZeroMQ之模式二 发布者订阅者(publish-subscribe)
- Redis:redission 源代码剖析2 编码解码过程
- Redis:redission 源代码剖析1 连接建立
- IOS 拼接参数与URL
- linux驱动之看门狗
- hibernate中的Query查询和criteria查询的区别
- LeetCode 28 : Implement strStr() (Java)
- PHP账号密码HashPassword加密方式破解代码实例
- Redis: Jedis 源代码剖析2- 发布者/订阅者模式剖析
- leetcode Basic Calculator
- ubuntu中的大小写
- jQuery插件——表单验证(jquery.validate.js)
- Coderforce 444cDZY Loves Colors(线段树)
- 南邮2015年程序设计周_个人股票信息管理系统
- 症状:可以上网,可以上QQ,不能登陆360安全卫士,360浏览器无法同步,有道词典等无法登陆,无法查询。
- maven项目打包为含依赖的可执行jar
- 向量模板