以前做online judge的时候用mysql+时间戳做消息队列,现在redis提供了一种现成的消息队列的模式,使用redis队列可以直接模拟消息通信的方式,在将并发转化为非并发时非常有用,同时通信的双方不需要关注彼此的信息,实现解耦合。比如用户提交了代码,我后台往消息队列压入题号,用户号,提交号,剩下的就交给判题脚本处理,判题脚本不需要了解其他信息,同时后台也不需要等待判题脚本执行结束,而是直接返回,避免了长时间占用连接。而判题脚本则是不停地从队列中取信息,并进行判题操作,同时及时更细数据库信息,标记此次判题的结果。
代码需要导入jedis的包.
producer.java(生产者)
package redis;
import redis.clients.jedis.Jedis;
public class producer implements Runnable{
Jedis jedis=null;
public producer(){
jedis=new Jedis("127.0.0.1",6379);
}
public void run(){//生产者不停生产
while(true){
String temp=String.valueOf((int)(Math.random()*1000));
jedis.lpush("redis-test2",temp);//创造内容
System.out.println("放入元素"+temp);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("生产者产生物品失败");
e.printStackTrace();
}
}
}
}
consumer.java(消费者)package redis;
import java.util.List;
import redis.clients.jedis.Jedis;
public class consumer implements Runnable{
Jedis jedis=null;
public consumer(){
jedis=new Jedis("127.0.0.1",6379);
}
@Override
public void run(){//不停地消费物品
while(true){
List<String>list=jedis.brpop(1,"redis-test2");
System.out.println("取出元素:"+list);//第一个参数代表阻塞几秒钟如果队列仍未空,则返回null,如果为0代表队列为空则始终阻塞着
if (list!=null){//返回结果是一个列表如果不为空,下标0是队列名,下标1是取出的元素,如果为空是null
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
consumer c=new consumer();
producer p=new producer();
Thread t1=new Thread(c);
t1.start();
Thread t2=new Thread(p);
t2.start();
}
}
使用发布/订阅模式,注意订阅是个阻塞方法,需要开启个线程单独处理
producer2.java(发布)
package redis;
import redis.clients.jedis.Jedis;
public class producer2 implements Runnable{
String source=null;
Jedis jedis=null;
public producer2(String source){
this.source=source;
jedis=new Jedis("127.0.0.1",6379);
}
@Override
public void run(){
while(true){
String temp=String.valueOf((int)(Math.random()*1000));
System.out.println("准备公布数字"+temp);
jedis.publish(source,temp);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("发布出问题了");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
consumer2 m=new consumer2("redis_chat");
Thread t=new Thread(m);
t.start();
producer2 p=new producer2("redis_chat");
Thread t2=new Thread(p);
t2.start();
}
}
订阅(consumer2.java)
package redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class consumer2 implements Runnable{
String source=null;
Jedis jedis=null;
JedisPubSub jedispubsub=null;
public consumer2(String source){
this.source=source;
jedis=new Jedis("127.0.0.1",6379);
jedispubsub=new JedisPubSub() {
@Override
public void onPMessage(String arg0, String arg1, String arg2) {
}
@Override
public void onPSubscribe(String arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onPUnsubscribe(String arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onSubscribe(String arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onUnsubscribe(String arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onMessage(String arg0, String arg1) {
System.out.println("获得信息:"+arg0+arg1);
}
};
}
@Override
public void run(){
jedis.subscribe(jedispubsub,source);
}
}