Redis 列表(List)方法使用详解

一、简介

  本文今天主要是介绍Redis 列表(List)的方法的使用,以及redis对应的Java实现该怎么用。因为篇幅问题,我这里写了一个测试类,引入 RedisTemplate对象,后面例子里就不一一引入了。大家理解就行,如果大家还不知道如何通过Spring Boot 整合redis则可以查看我之前的文章:SpringBoot整合redis(redis支持单节点和集群)

package com.alian.datastruct;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RedisListTest {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
}

二、常用方法

2.1、LPUSH、RPUSH

  • LPUSH 将一个或多个值插入到列表头部
  • RPUSH 将一个或多个值插入到列表尾部

语法

LPUSH KEY_NAME VALUE1 VALUE2.. VALUEn
RPUSH KEY_NAME VALUE1 VALUE2.. VALUEn

命令操作

127.0.0.1:6379> lpush list1 python
(integer) 1
127.0.0.1:6379> lpush list1 Java
(integer) 2
127.0.0.1:6379> rpush list1 kotlin
(integer) 3
127.0.0.1:6379> lrange list1 0 -1
1) "Java"
2) "python"
3) "kotlin"

  需要注意的是,使用LPUSHRPUSH,如果key不存在,就会自动创建这个key,这里的key就是list1

Java操作

    @Test
    public void leftPushAndRightPush() {
        String redisKey="list1";
        redisTemplate.delete(redisKey);
        // 从列表的左边插入
        redisTemplate.opsForList().leftPush(redisKey,"Python");
        redisTemplate.opsForList().leftPush(redisKey,"Java");
        // 从列表的右边插入
        redisTemplate.opsForList().rightPush(redisKey,"Kotlin");
        // 输出全部列表
        List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表的信息:{}", list);
    }
列表的信息:[Java, python, kotlin]

2.2、LPUSHX、RPUSHX

  • LPUSHX 将一个值插入到已存在的列表头部
  • RPUSHX 将一个值插入到已存在的列表尾部

语法

LPUSHX KEY_NAME VALUE1 VALUE2.. VALUEn
RPUSHX KEY_NAME VALUE1 VALUE2.. VALUEn

命令操作

127.0.0.1:6379> lpushx list2 java
(integer) 0
127.0.0.1:6379> rpushx list2 javascript
(integer) 0
127.0.0.1:6379> lpush list2 kotlin
(integer) 1
127.0.0.1:6379> lpushx list2 go
(integer) 2
127.0.0.1:6379> rpushx list2 ios
(integer) 3
127.0.0.1:6379> lrange list2 0 -1
1) "go"
2) "kotlin"
3) "ios"
  • 使用LPUSHXRPUSHX添加时,由于key(list2)不存在,则插入数据失败
  • 使用LPUSH加入kotlin后,就自动创建了key(list2
  • 再使用LPUSHXRPUSHX添加时,由于key(list2)存在,在列表的左侧插入go,右侧插入ios

Java操作

    @Test
    public void leftPushXAndRightPushX() {
        redisTemplate.delete(REDIS_KEY);
        String redisKey="list2";
        // 从列表的左边插入(如果key:list2存在)
        redisTemplate.opsForList().leftPushIfPresent(redisKey,"Java");
        // 从列表的右边插入(如果key:list2存在)
        redisTemplate.opsForList().rightPushIfPresent(redisKey,"Javascript");

        // 从列表的左边插入
        redisTemplate.opsForList().leftPush(redisKey,"kotlin");
        // 从列表的左边插入(如果key:list2存在)
        redisTemplate.opsForList().leftPushIfPresent(redisKey,"go");
        // 从列表的右边插入(如果key:list2存在)
        redisTemplate.opsForList().rightPushIfPresent(redisKey,"ios");
        // 输出全部列表
        List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表的信息:{}", list);
    }
列表的信息:[go, kotlin, ios]

2.3、LPOP、RPOP

  • LPOP 移除列表的第一个元素,返回值为移除的元素
  • RPOP 移除列表的最后一个元素,返回值为移除的元素

语法

LPOP KEY_NAME
RPOP KEY_NAME

命令操作

127.0.0.1:6379> lpush list3 Python Java Kotlin Go
(integer) 4
127.0.0.1:6379> lpop list3
"Go"
127.0.0.1:6379> rpop list3
"Python"
127.0.0.1:6379> lrange list3 0 -1
1) "Kotlin"
2) "Java"
  • 先初始化一个列表(list3)得到:Go、Kotlin、Java、Python
  • 从列表(list3)的左边弹出 Go
  • 从列表(list3)的右边边弹出 Python
  • 剩下的列表(list3)的元素:Kotlin、Java

Java操作

    @Test
    public void leftPopAndRightPop() {
        String redisKey="list3";
        redisTemplate.delete(redisKey);
        // 给列表list3插入多个数据
        redisTemplate.opsForList().leftPushAll(redisKey,"Python","Java","Kotlin","Go");
        // 从列表的左边弹出数据
        Object leftValue = redisTemplate.opsForList().leftPop(redisKey);
        log.info("左边弹出的数据:{}", leftValue);
        // 从列表的右边边弹出数据
        Object rightValue = redisTemplate.opsForList().rightPop(redisKey);
        log.info("右边边弹出的数据:{}", rightValue);
        // 输出全部列表
        List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表的信息:{}", list);
    }
左边弹出的数据:Go
右边边弹出的数据:Python
列表的信息:[Kotlin, Java]

2.4、RPOPLPUSH

  • RPOPLPUSH 移除列表的最后一个元素,并将该元素添加到另一个列表的头部并返回

语法

RPOPLPUSH SOURCE_KEY_NAME DESTINATION_KEY_NAME

命令操作

127.0.0.1:6379> rpush list4 Python Java Kotlin Go
(integer) 4
127.0.0.1:6379> rpoplpush list4 anotherList
"Go"
127.0.0.1:6379> lrange list4 0 -1
1) "Python"
2) "Java"
3) "Kotlin"
  • 先初始化一个列表(list4)得到:Python、Java、Kotlin、Go
  • 从列表(list4)的左边弹出 Go插入到新的列表(anotherList
  • 剩下的列表(list4)的元素:Python、Java、Kotlin

Java操作

    @Test
    public void rightPopLeftPush() {
        String redisKey = "list4";
        redisTemplate.delete(redisKey);
        redisTemplate.delete("anotherList");
        // 给列表list4插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin","Go");

        // 从列表的右边弹出一个原素,插入到另外一个列表,
        redisTemplate.opsForList().rightPopAndLeftPush(redisKey, "anotherList");
        // 输出列表信息
        List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("原列表的信息:{}", list);
        // 输出新列表信息
        List<Object> anotherList = redisTemplate.opsForList().range("anotherList", 0, -1);
        log.info("新列表的信息:{}", anotherList);
    }
原列表的信息:[Python, Java, Kotlin]
新列表的信息:[Go]

2.5、LEN

  • LEN 获取列表长度

语法

LLEN KEY_NAME 

命令操作

127.0.0.1:6379> rpush list5 Python Java Kotlin Go
(integer) 4
127.0.0.1:6379> llen list5
(integer) 4
127.0.0.1:6379> llen list0
(integer) 0
  • 初始化列表(list5)得到:Python、Java、Kotlin、Go
  • 通过 llen 获取列表的长度,得到 4
  • 当列表(list0)不存在,长度为0

Java操作

    @Test
    public void length() {
        String redisKey = "list5";
        redisTemplate.delete(redisKey);
        // 给列表list5插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin","Go");
        // 获取列表的长度
        Long size = redisTemplate.opsForList().size(redisKey);
        log.info("列表的长度:{}", size);
    }
列表的长度:4

2.6、LINDEX

  • LINDEX 通过索引获取列表中的元素

语法

LINDEX KEY_NAME INDEX_POSITION 

命令操作

  列表从左往右是从 0 开始,列表从右往左是从 -1 开始

127.0.0.1:6379> rpush list6 Python Java Kotlin Go
(integer) 4
127.0.0.1:6379> lindex list6 0
"Python"
127.0.0.1:6379> lindex list6 1
"Java"
127.0.0.1:6379> lindex list6 2
"Kotlin"
127.0.0.1:6379> lindex list6 -1
"Go"
127.0.0.1:6379> lindex list6 -2
"Kotlin"
127.0.0.1:6379> lindex list6 -3
"Java"
  • 先初始化一个列表(list6)得到:Python、Java、Kotlin、Go
  • 获取列表(list6)中索引为 0 的数据,得到 Python
  • 获取列表(list6)中索引为 1 的数据,得到 Java
  • 获取列表(list6)中索引为 2 的数据,得到 Kotlin
  • 获取列表(list6)中索引为 -1 的数据,得到 Go
  • 获取列表(list6)中索引为 -2 的数据,得到 Kotlin
  • 获取列表(list6)中索引为 -3 的数据,得到 Java

Java操作

    @Test
    public void index() {
        String redisKey = "list6";
        redisTemplate.delete(redisKey);
        // 给列表list6插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin","Go");

        // 获取列表中索引为【0】的数据
        Object value0 = redisTemplate.opsForList().index(redisKey, 0);
        log.info("列表中索引为【0】对应的值:{}", value0);
        // 获取列表中索引为【1】的数据
        Object value1 = redisTemplate.opsForList().index(redisKey, 1);
        log.info("列表中索引为【1】对应的值:{}", value1);
        // 获取列表中索引为【2】的数据
        Object value2 = redisTemplate.opsForList().index(redisKey, 2);
        log.info("列表中索引为【2】对应的值:{}", value2);

        // 获取列表中索引为【-1】的数据
        Object value3 = redisTemplate.opsForList().index(redisKey, -1);
        log.info("列表中索引为【-1】对应的值:{}", value3);
        // 获取列表中索引为【-2】的数据
        Object value4 = redisTemplate.opsForList().index(redisKey, -2);
        log.info("列表中索引为【-2】对应的值:{}", value4);
        // 获取列表中索引为【-3】的数据
        Object value5 = redisTemplate.opsForList().index(redisKey, -3);
        log.info("列表中索引为【-3】对应的值:{}", value5);
    }
列表中索引为【0】对应的值:Python
列表中索引为【1】对应的值:Java
列表中索引为【2】对应的值:Kotlin
列表中索引为【-1】对应的值:Go
列表中索引为【-2】对应的值:Kotlin
列表中索引为【-3】对应的值:Java

2.7、LRANGE

  • LRANGE 获取列表指定范围内的元素

语法

LRANGE KEY_NAME START END

命令操作

  返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。如果是负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推

127.0.0.1:6379> rpush list7 Python Java Kotlin Go Javascript
(integer) 5
127.0.0.1:6379> lrange list7 0 -1
1) "Python"
2) "Java"
3) "Kotlin"
4) "Go"
5) "Javascript"
127.0.0.1:6379> lrange list7 1 3
1) "Java"
2) "Kotlin"
3) "Go"
127.0.0.1:6379> lrange list7 -3 -1
1) "Kotlin"
2) "Go"
3) "Javascript"
  • 先初始化一个列表(list7 )得到:Python、Java、Kotlin、Go、Javascript
  • 获取列表(list7)中索引从 0 -1 的列表,得到Python、Java、Kotlin、Go、Javascript
  • 获取列表(list7)中索引从 1 3 的列表,得到Java、Kotlin、Go
  • 获取列表(list7)中索引从 -3 -1 的列表,得到Kotlin、Go、Javascript

Java操作

    @Test
    public void range() {
        String redisKey = "list7";
        redisTemplate.delete(redisKey);
        // 给列表list7插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin","Go","Javascript");

        // 获取指定范围的列表数据
        List<Object> result1 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表中索引为【0】到【-1】的列表值:{}", result1);
        List<Object> result2 = redisTemplate.opsForList().range(redisKey, 1, 3);
        log.info("列表中索引为【1】到【3】的列表值:{}", result2);
        List<Object> result3 = redisTemplate.opsForList().range(redisKey, -3, -1);
        log.info("列表中索引为【-3】到【-1】的列表值:{}", result3);
    }
列表中索引为【0】到【-1】的列表值:[Python, Java, Kotlin, Go, Javascript]
列表中索引为【1】到【3】的列表值:[Java, Kotlin, Go]
列表中索引为【-3】到【-1】的列表值:[Kotlin, Go, Javascript]

2.8、LSET

  • LSET 通过索引设置列表元素的值

语法

LSET KEY_NAME INDEX VALUE

命令操作

127.0.0.1:6379> rpush list8 Python Java Kotlin Go Javascript
(integer) 5
127.0.0.1:6379> lset list8 3 IOS
OK
127.0.0.1:6379> lset list8 4 Android
OK
127.0.0.1:6379> lrange list8 0 -1
1) "Python"
2) "Java"
3) "Kotlin"
4) "IOS"
5) "Android"
  • 先初始化一个列表(list8 )得到:Python、Java、Kotlin、Go、Javascript
  • 把列表(list8)中索引为 3 的数据改成,IOS
  • 把列表(list8)中索引为 4 的数据改成,Android
  • 获取列表(list8)中索引从 0 -1 的列表,得到Python、Java、Kotlin、IOS、Android

Java操作

    @Test
    public void set() {
        String redisKey = "list8";
        redisTemplate.delete(redisKey);
        // 给列表list8插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin","Go","Javascript");

        // 把索引3和4分别设置为IOS、Android
        redisTemplate.opsForList().set(redisKey, 3, "IOS");
        redisTemplate.opsForList().set(redisKey, 4, "Android");
        // 获取列表中数据
        List<Object> result1 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表中的数据为:{}", result1);
    }
列表中数据为:[Python, Java, Kotlin, IOS, Android]

2.9、LINSERT

  • LINSERT 在列表的元素前或者后插入元素

语法

LINSERT key BEFORE|AFTER pivot value

命令操作

127.0.0.1:6379> rpush list9 Python Java Kotlin
(integer) 3
127.0.0.1:6379> linsert list9 before Java IOS
(integer) 4
127.0.0.1:6379> linsert list9 after Java Android
(integer) 5
127.0.0.1:6379> lrange list9 0 -1
1) "Python"
2) "IOS"
3) "Java"
4) "Android"
5) "Kotlin"
  • 先初始化一个列表(list9 )得到:Python、Java、Kotlin
  • IOS插入到列表(list9)中值为 Java 的前面
  • Android插入到列表(list9)中值为 Java 的后面
  • 获取列表(list9)中索引从 0 -1 的列表,得到Python、IOS、Java、Android、Kotlin

Java操作

    @Test
    public void insert() {
        String redisKey = "list9";
        redisTemplate.delete(redisKey);
        // 给列表list9插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python","Java","Kotlin");

        // 在Java前添加IOS
        redisTemplate.opsForList().leftPush(redisKey,"Java","IOS");
        // 在Java后添加Android
        redisTemplate.opsForList().rightPush(redisKey,"Java","Android");
        // 获取列表中数据
        List<Object> result1 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("列表中数据为:{}", result1);
    }
列表中数据为:[Python, IOS, Java, Android, Kotlin]

2.10、LTRIM

  • LTRIM 对一个列表进行裁剪(trim),让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

语法

LTRIM KEY_NAME START STOP

命令操作

127.0.0.1:6379> rpush list10 Python Java Kotlin Go Javascript IOS Android
(integer) 7
127.0.0.1:6379> ltrim list10 2 -1
OK
127.0.0.1:6379> lrange list10 0 -1
1) "Kotlin"
2) "Go"
3) "Javascript"
4) "IOS"
5) "Android"
127.0.0.1:6379> ltrim list10 0 -3
OK
127.0.0.1:6379> lrange list10 0 -1
1) "Kotlin"
2) "Go"
3) "Javascript"
127.0.0.1:6379> ltrim list10 1 2
OK
127.0.0.1:6379> lrange list10 0 -1
1) "Go"
2) "Javascript"
  • 先初始化一个列表(list10 )得到:Python、Java、Kotlin、Go、Javascript、IOS、Android
  • 通过 ltrim 方法去除头部两个元素,得到Kotlin、Go、Javascript、IOS、Android
  • 通过 ltrim 方法去除尾部两个元素,得到Kotlin、Go、Javascript
  • 通过 ltrim 方法截取从1到2的元素,得到Go、Javascript

Java操作

    @Test
    public void trim() {
        String redisKey = "list10";
        redisTemplate.delete(redisKey);

        // 给列表list10插入数据
        redisTemplate.opsForList().rightPushAll(redisKey,"Python", "Java", "Kotlin", "Go", "Javascript","IOS","Android");
        List<Object> result = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("初始数据为:{}", result);

        // 去除头部两个元素
        redisTemplate.opsForList().trim(redisKey,2,-1);
        // 获取列表中数据
        List<Object> result1 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("去除头部两个元素后列表中数据为:{}", result1);

        // 去除尾部两个元素
        redisTemplate.opsForList().trim(redisKey,0,-3);
        // 获取列表中数据
        List<Object> result2 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("去除尾部两个元素后列表中数据为:{}", result2);

        // 截取列表中索引从1到2的数据
        redisTemplate.opsForList().trim(redisKey, 1, 2);
        // 获取列表中数据
        List<Object> result3 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("截取列表中索引从1到2的数据后:{}", result3);
    }
初始数据为:[Python, Java, Kotlin, Go, Javascript, IOS, Android]
去除头部两个元素后列表中数据为:[Kotlin, Go, Javascript, IOS, Android]
去除尾部两个元素后列表中数据为:[Kotlin, Go, Javascript]
截取列表中索引从1到2的数据后:[Go, Javascript]

2.11、LREM

  • LTRIM 移除列表元素

语法

LREM KEY_NAME count VALUE
  • count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT
  • count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值
  • count = 0 : 移除表中所有与 VALUE 相等的值

命令操作

127.0.0.1:6379> rpush list11 Java Java Kotlin Java Java IOS Java
(integer) 7
127.0.0.1:6379> lrem list11 2 Java
(integer) 2
127.0.0.1:6379> lrange list11 0 -1
1) "Kotlin"
2) "Java"
3) "Java"
4) "IOS"
5) "Java"
127.0.0.1:6379> lrem list11 -1 Java
(integer) 1
127.0.0.1:6379> lrange list11 0 -1
1) "Kotlin"
2) "Java"
3) "Java"
4) "IOS"
127.0.0.1:6379> lrem list11 0 Java
(integer) 2
127.0.0.1:6379> lrange list11 0 -1
1) "Kotlin"
2) "IOS"
  • 先初始化一个列表(list11 )得到:Java、Java、Kotlin、Java、Java、IOS、Java
  • 通过 lrem 方法去除头部2个Java ,得到Kotlin、Java、Java、IOS、Java
  • 通过 lrem 方法去除尾部1个Java ,得到Kotlin、Java、Java、IOS
  • 通过 lrem 方法去除所有Java ,得到Kotlin、IOS
    Java操作
    @Test
    public void count() {
        String redisKey = "list11";
        redisTemplate.delete(redisKey);

        // 给列表list11插入数据
        redisTemplate.opsForList().rightPushAll(redisKey, "Java", "Java", "Kotlin", "Java", "Java", "IOS", "Java");

        // 从头部开始移除2个Java
        redisTemplate.opsForList().remove(redisKey,2,"Java");
        // 获取列表中数据
        List<Object> result1 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("从头部开始移除2个Java值后:{}", result1);

        // 从尾部部开始移除1个Java
        redisTemplate.opsForList().remove(redisKey,-1,"Java");
        // 获取列表中数据
        List<Object> result2 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("从尾部部开始移除1个Java值后:{}", result2);

        // 移除列表中的所有的Java
        redisTemplate.opsForList().remove(redisKey,0,"Java");
        // 获取列表中数据
        List<Object> result3 = redisTemplate.opsForList().range(redisKey, 0, -1);
        log.info("移除列表中的所有的Java值后:{}", result3);
    }
从头部开始移除2个Java值后:[Kotlin, Java, Java, IOS, Java]
从尾部部开始移除1个Java值后:[Kotlin, Java, Java, IOS]
移除列表中的所有的Java值后:[Kotlin, IOS]

2.12、BLPOP、BRPOP

  • BLPOP 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
  • BRPOP 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

语法

BLPOP LIST1 LIST2 ... LISTn TIMEOUT
BRPOP LIST1 LIST2 ... LISTn TIMEOUT

命令操作

127.0.0.1:6379> rpush list12 Java Python
(integer) 2
127.0.0.1:6379> blpop list12 10
1) "list12"
2) "Java"
127.0.0.1:6379> brpop list12 10
1) "list12"
2) "Python"
127.0.0.1:6379> blpop list12 10
(nil)
(10.01s)
127.0.0.1:6379> brpop list12 10
(nil)
(10.01s)
  • 先初始化一个列表(list12 )得到:Java、Python
  • 通过 blpop 方法弹出头部一个元素,得到Java
  • 通过 brpop 方法弹出尾部一个元素,得到Python,此时列表为空
  • 通过 blpop 方法弹出头部一个元素,结果10秒后超时(列表为空)
  • 通过 brpop 方法弹出尾部一个元素,结果10秒后超时(列表为空)

终端一

127.0.0.1:6379> blpop list12 10
(nil)
(10.05s)
127.0.0.1:6379> blpop list12 10

终端二

127.0.0.1:6379> lpush list12 Scala
(integer) 1

  此时终端一会马上得到结果,详细见下图

在这里插入图片描述

  • 在终端一 blpop 方法弹出空列表 list12 头部一个元素,如果没有数据则10秒后超时
  • 在终端二中我们给空列表 list12 ,插入一个数据 Scala
  • 终端一马上弹出了,终端二插入的数据 Scala ,阻塞终止

Java操作

    @Test
    public void bLeftPopAndBRightPop() {
        String redisKey = "list12";
        redisTemplate.delete(redisKey);
        // 给列表list12插入数据
        redisTemplate.opsForList().leftPushAll(redisKey, "Python", "Java");

        // 从列表头部弹出元素,超时时间为30秒
        Object value1 = redisTemplate.opsForList().leftPop(redisKey, 30, TimeUnit.SECONDS);
        log.info("从列表头部阻塞弹出元素:{}", value1);
        // 从列表尾部弹出元素,超时时间为30秒
        Object value2 = redisTemplate.opsForList().rightPop(redisKey,30, TimeUnit.SECONDS);
        log.info("从列表尾部阻塞弹出元素:{}", value2);

        try {
            // 此时是空列表了,继续头部弹出,此时会阻塞,如果30秒内列表还有元素,就会超时
            redisTemplate.opsForList().leftPop(redisKey,30, TimeUnit.SECONDS);
//            redisTemplate.opsForList().rightPop(redisKey,30, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.info("阻塞弹出数据超时");
        }
    }
从列表头部阻塞弹出元素:Java
从列表尾部阻塞弹出元素:Python
阻塞弹出数据超时

2.13、BRPOPLPUSH

  • BRPOPLPUSH 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

语法

BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT 

命令操作

127.0.0.1:6379> rpush list13 Java Python
(integer) 2
127.0.0.1:6379> brpoplpush list13 newlist 10
"Python"
127.0.0.1:6379> brpoplpush list13 newlist 10
"Java"
127.0.0.1:6379> brpoplpush list13 newlist 10
(nil)
(10.02s)
127.0.0.1:6379> lrange newlist 0 -1
1) "Java"
2) "Python"
  • 先初始化一个列表(list13 )得到:Java、Python
  • 通过 brpoplpush 方法弹出尾部一个元素,得到Python,并插入到一个新的列表 newlist
  • 通过 brpoplpush 方法弹出尾部一个元素,得到Java,并插入到一个新的列表 newlist ,此时列表list13 为空
  • 通过 brpoplpush 方法弹出尾部一个元素,结果10秒后超时(列表为空)
  • 通过 lrange 方法查看新列表( newlist )的数据,得到Java、Python

同样的,为了验证阻塞,我们开启另外一个终端,往空列表 list13 写入数据

终端二

127.0.0.1:6379> lpush list13 Scala
(integer) 1

终端一

127.0.0.1:6379> brpoplpush list13 newlist 10
(nil)
(10.05s)
127.0.0.1:6379> brpoplpush list13 newlist 10
"Scala"
(3.57s)
127.0.0.1:6379> lrange newlist 0 -1
1) "Scala"
2) "Java"
3) "Python"
  • 在终端一 brpoplpush 方法弹出空列表 list13 尾部一个元素,如果没有数据则10秒后超时
  • 在终端二中我们给空列表 list13 ,插入一个数据 Scala
  • 终端一马上弹出了,终端二插入的数据 Scala ,阻塞终止
  • 通过 lrange 方法查看新列表( newlist )的数据,得到Scala、Java、Python

Java操作

    @Test
    public void bRightPopAndLeftPush() {
        String redisKey = "list13";
        redisTemplate.delete(redisKey);
        // 给列表list13插入数据
        redisTemplate.opsForList().leftPushAll(redisKey, "Python", "Java", "Kotlin", "Go");

        // 从列表尾部弹出元素,插入到另外一个列表的头部,超时时间为30秒
        redisTemplate.opsForList().rightPopAndLeftPush(redisKey,"newList",30, TimeUnit.SECONDS);
    }
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值