redis订阅发布示例

下面的代码使用redis实现订阅/发布。

在redis中可以同时订阅多个频道,如果有消息发布是redis会发出通知。jedis中提供了JedisPubSub抽象类来提供发布/订阅的机制,在实际应用中需要实现JedisPubSub类。

package com.qinying.demo.redis;
import redis.clients.jedis.JedisPubSub;

public class Subscriber extends JedisPubSub {
    @Override
    public void onMessage(String channel, String message) {
        super.onMessage(channel, message);
        System.out.println(channel + ":" + message);
    }
}

上面的类是从JedisPubSub继承的类,我要用它来订阅一些频道,并获得消息。

main方法如下

package com.qinying.demo.redis;

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class Program {
    public static final String CHANNEL_NAME = "commonChannel";
    public static Logger logger = Logger.getLogger(Program.class);

    public static void main(String[] args) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        JedisPool jedisPool = new JedisPool(poolConfig, "10.2.2.206", 6379, 0);
        final Jedis subscriberJedis = jedisPool.getResource();
        final Subscriber subscriber = new Subscriber();
        final Jedis subscriberJedis2 = jedisPool.getResource();
        final Subscriber subscriber2 = new Subscriber();
        new Thread(new Runnable() {
            public void run() {
                try {
                    logger.info("Subscribing to \"commonChannel\". This thread will be blocked.");
                    subscriberJedis.subscribe(subscriber, CHANNEL_NAME);
                    logger.info("Subscription ended.");
                } catch (Exception e) {
                    logger.error("Subscribing failed.", e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                try {
                    logger.info("Subscribing to \"commonChannel\". This thread will be blocked.");
                    subscriberJedis2.subscribe(subscriber2, CHANNEL_NAME);
                    logger.info("Subscription ended.");
                } catch (Exception e) {
                    logger.error("Subscribing failed.", e);
                }
            }
        }).start();
        //subscriber.unsubscribe();
        //jedisPool.returnResource(subscriberJedis);
    }
}

在上面的例子中,我们使用JedisPool来获得Jedis的实例。 Jedis类是非线程安全的,但是JedisPool是线程安全的。我使用了两个Jedis实例,一个用来发布消息,另一个订阅频道。

我在另外一个线程中实现订阅。

下面的类实现发布消息到redis的频道中。

package com.qinying.demo.redis;

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class Publisher {
    private static final Logger logger = Logger.getLogger(Publisher.class);

    public static void main(String[] args) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        JedisPool jedisPool = new JedisPool(poolConfig, "10.2.2.206", 6379, 0);
        final Jedis publisherJedis = jedisPool.getResource();

        publisherJedis.publish("commonChannel", "hello");
    }
}

上面的类获得用户的控制台输入,然后发布到redis channel,当用户键入quit时则退出循环

关键点如下:
  • 要在单独的线程中订阅, 因为subscribe会阻塞当前线程的执行。 你可以使用一个PubSub实例来订阅多个Channel
  • 注意Jedis实例是非线程安全的
  • 当需要创建多个jedis实例时要使用JedisPool类,当使用完jedis对象时要放回JedisPool。

你可能感兴趣的:(redis订阅发布示例)