一、application-dev.yml

spring:
#redis
  redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        #连接池最大连接数(负值表示没有限制)
        max-active: -1
        #最大阻塞时间,单位ms
        max-wait: 2000
        #最大空闲连接数
        max-idle: 100
        #最小空闲连接数
        min-idle: 0
    #连接超时时间,单位ms
    timeout: 2000

二、RedisConfig

 1 package com.miaoshaproject.config;
 2 
 3 import com.fasterxml.jackson.annotation.JsonAutoDetect;
 4 import com.fasterxml.jackson.annotation.PropertyAccessor;
 5 import com.fasterxml.jackson.databind.ObjectMapper;
 6 import org.springframework.context.annotation.Bean;
 7 import org.springframework.context.annotation.Configuration;
 8 import org.springframework.data.redis.connection.RedisConnectionFactory;
 9 import org.springframework.data.redis.core.RedisTemplate;
10 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
11 import org.springframework.data.redis.serializer.StringRedisSerializer;
12 
13 /*
14    @Author wangshuo
15    @Date 2022/5/15, 9:42
16    Please add a comment
17 */
18 @Configuration
19 public class RedisConfig {
20 
21     @Bean
22     @SuppressWarnings("all")
23     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
24 
25         RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
26         template.setConnectionFactory(factory);
27         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
28         ObjectMapper om = new ObjectMapper();
29         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
30         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
31         jackson2JsonRedisSerializer.setObjectMapper(om);
32         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
33         // key采用String的序列化方式
34         template.setKeySerializer(stringRedisSerializer);
35 
36         // hash的key也采用String的序列化方式
37         template.setHashKeySerializer(stringRedisSerializer);
38 
39         // value序列化方式采用jackson
40         template.setValueSerializer(jackson2JsonRedisSerializer);
41 
42         // hash的value序列化方式采用jackson
43         template.setHashValueSerializer(jackson2JsonRedisSerializer);
44 
45         template.afterPropertiesSet();
46         return template;
47     }
48 }

三、RedisUtil

  1 package com.miaoshaproject.util.redis;
  2 
  3 import lombok.extern.slf4j.Slf4j;
  4 import org.springframework.beans.factory.annotation.Autowired;
  5 import org.springframework.data.redis.core.RedisTemplate;
  6 import org.springframework.stereotype.Component;
  7 import org.springframework.util.CollectionUtils;
  8 
  9 import java.util.*;
 10 import java.util.concurrent.TimeUnit;
 11 
 12 /**
 13  * @Author wangshuo
 14  * @Date 2022/5/15, 15:30
 15  * Please add a comment
 16  */
 17 
 18 @Component
 19 @Slf4j
 20 public class RedisUtil {
 21     @Autowired
 22     public RedisTemplate<String, Object> redisTemplate;
 23 
 24     // =============================1-common============================
 25 
 26     /**
 27      * 指定缓存失效时间
 28      *
 29      * @param key  键
 30      * @param time 时间(秒)
 31      * @return
 32      */
 33     public boolean expire(String key, long time) {
 34         try {
 35             if (time > 0) {
 36                 redisTemplate.expire(key, time, TimeUnit.SECONDS);
 37             }
 38             return true;
 39         } catch (Exception e) {
 40             log.error(key, e);
 41             return false;
 42         }
 43     }
 44 
 45     /**
 46      * 根据key 获取过期时间
 47      *
 48      * @param key 键 不能为null
 49      * @return 时间(秒) 返回0代表为永久有效
 50      */
 51     public long getExpire(String key) {
 52         return redisTemplate.getExpire(key, TimeUnit.SECONDS);
 53     }
 54 
 55     /**
 56      * 判断key是否存在
 57      *
 58      * @param key 键
 59      * @return true 存在 false不存在
 60      */
 61     public boolean hasKey(String key) {
 62         try {
 63             return redisTemplate.hasKey(key);
 64         } catch (Exception e) {
 65             log.error(key, e);
 66             return false;
 67         }
 68     }
 69 
 70     /**
 71      * 删除缓存
 72      *
 73      * @param key 可以传一个值 或多个
 74      */
 75     @SuppressWarnings("unchecked")
 76     public void del(String... key) {
 77         if (key != null && key.length > 0) {
 78             if (key.length == 1) {
 79                 redisTemplate.delete(key[0]);
 80             } else {
 81                 redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
 82             }
 83         }
 84     }
 85 
 86     // ============================2-String=============================
 87 
 88     /**
 89      * 普通缓存获取
 90      *
 91      * @param key 键
 92      * @return 93      */
 94     public Object get(String key) {
 95         return key == null ? null : redisTemplate.opsForValue().get(key);
 96     }
 97 
 98     /**
 99      * 普通缓存放入
100      *
101      * @param key   键
102      * @param value 值
103      * @return true成功 false失败
104      */
105     public boolean set(String key, Object value) {
106         try {
107             redisTemplate.opsForValue().set(key, value);
108             return true;
109         } catch (Exception e) {
110             log.error(key, e);
111             return false;
112         }
113 
114     }
115 
116     /**
117      * 插入数据,若数据已存在,返回false
118      *
119      * @param key   键
120      * @param value 值
121      * @return true成功 false失败
122      */
123     public boolean setnx(String key, Object value) {
124         try {
125             Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, value);
126             if (aBoolean)
127                 return true;
128             else
129                 return false;
130         } catch (Exception e) {
131             log.error(key, e);
132             return false;
133         }
134     }
135 
136     /**
137      * 插入数据,若数据已存在,返回false 设置过期时间
138      *
139      * @param key   键
140      * @param value 值
141      * @return true成功 false失败
142      */
143     public boolean setnx(String key, Object value, long time) {
144         try {
145             Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
146             if (aBoolean)
147                 return true;
148             else
149                 return false;
150         } catch (Exception e) {
151             log.error(key, e);
152             return false;
153         }
154     }
155 
156     /**
157      * 普通缓存放入并设置时间
158      *
159      * @param key   键
160      * @param value 值
161      * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
162      * @return true成功 false 失败
163      */
164     public boolean set(String key, Object value, long time) {
165         try {
166             if (time > 0) {
167                 redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
168             } else {
169                 set(key, value);
170             }
171             return true;
172         } catch (Exception e) {
173             log.error(key, e);
174             return false;
175         }
176     }
177 
178     /**
179      * 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。
180      *
181      * @param key   键
182      * @param delta 要增加几(大于0)
183      * @return
184      */
185     public long incr(String key, long delta) {
186         if (delta < 0) {
187             throw new RuntimeException("递增因子必须大于0");
188         }
189         return redisTemplate.opsForValue().increment(key, delta);
190     }
191 
192     /**
193      * 递减
194      *
195      * @param key   键
196      * @param delta 要减少几(小于0)
197      * @return
198      */
199     public long decr(String key, long delta) {
200         if (delta < 0) {
201             throw new RuntimeException("递减因子必须大于0");
202         }
203         return redisTemplate.opsForValue().increment(key, -delta);
204     }
205 
206     // ================================3-Map=================================
207 
208     /**
209      * HashGet
210      *
211      * @param key  键 不能为null
212      * @param item 项 不能为null
213      * @return214      */
215     public Object hget(String key, String item) {
216         return redisTemplate.opsForHash().get(key, item);
217     }
218 
219     /**
220      * 获取hashKey对应的所有键值
221      *
222      * @param key 键
223      * @return 对应的多个键值
224      */
225     public Map<Object, Object> hmget(String key) {
226         return redisTemplate.opsForHash().entries(key);
227     }
228 
229     /**
230      * HashSet
231      *
232      * @param key 键
233      * @param map 对应多个键值
234      * @return true 成功 false 失败
235      */
236     public boolean hmset(String key, Map<String, Object> map) {
237         try {
238             redisTemplate.opsForHash().putAll(key, map);
239             return true;
240         } catch (Exception e) {
241             log.error(key, e);
242             return false;
243         }
244     }
245 
246     /**
247      * HashSet 并设置时间
248      *
249      * @param key  键
250      * @param map  对应多个键值
251      * @param time 时间(秒)
252      * @return true成功 false失败
253      */
254     public boolean hmset(String key, Map<String, Object> map, long time) {
255         try {
256             redisTemplate.opsForHash().putAll(key, map);
257             if (time > 0) {
258                 expire(key, time);
259             }
260             return true;
261         } catch (Exception e) {
262             log.error(key, e);
263             return false;
264         }
265     }
266 
267     /**
268      * 向一张hash表中放入数据,如果不存在将创建
269      *
270      * @param key   键
271      * @param item  项
272      * @param value 值
273      * @return true 成功 false失败
274      */
275     public boolean hset(String key, String item, Object value) {
276         try {
277             redisTemplate.opsForHash().put(key, item, value);
278             return true;
279         } catch (Exception e) {
280             log.error(key, e);
281             return false;
282         }
283     }
284 
285     /**
286      * 向一张hash表中放入数据,如果不存在将创建
287      *
288      * @param key   键
289      * @param item  项
290      * @param value 值
291      * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
292      * @return true 成功 false失败
293      */
294     public boolean hset(String key, String item, Object value, long time) {
295         try {
296             redisTemplate.opsForHash().put(key, item, value);
297             if (time > 0) {
298                 expire(key, time);
299             }
300             return true;
301         } catch (Exception e) {
302             log.error(key, e);
303             return false;
304         }
305     }
306 
307     /**
308      * 删除hash表中的值
309      *
310      * @param key  键 不能为null
311      * @param item 项 可以使多个 不能为null
312      */
313     public void hdel(String key, Object... item) {
314         redisTemplate.opsForHash().delete(key, item);
315     }
316 
317     /**
318      * 判断hash表中是否有该项的值
319      *
320      * @param key  键 不能为null
321      * @param item 项 不能为null
322      * @return true 存在 false不存在
323      */
324     public boolean hHasKey(String key, String item) {
325         return redisTemplate.opsForHash().hasKey(key, item);
326     }
327 
328     /**
329      * hash递增 如果不存在,就会创建一个 并把新增后的值返回
330      *
331      * @param key  键
332      * @param item 项
333      * @param by   要增加几(大于0)
334      * @return
335      */
336     public double hincr(String key, String item, double by) {
337         return redisTemplate.opsForHash().increment(key, item, by);
338     }
339 
340     /**
341      * hash递减
342      *
343      * @param key  键
344      * @param item 项
345      * @param by   要减少记(小于0)
346      * @return
347      */
348     public double hdecr(String key, String item, double by) {
349         return redisTemplate.opsForHash().increment(key, item, -by);
350     }
351 
352     // ============================4-set=============================
353 
354     /**
355      * 根据key获取Set中的所有值
356      *
357      * @param key 键
358      * @return
359      */
360     public Set<Object> sGet(String key) {
361         try {
362             return redisTemplate.opsForSet().members(key);
363         } catch (Exception e) {
364             log.error(key, e);
365             return null;
366         }
367     }
368 
369     /**
370      * 根据value从一个set中查询,是否存在
371      *
372      * @param key   键
373      * @param value 值
374      * @return true 存在 false不存在
375      */
376     public boolean sHasKey(String key, Object value) {
377         try {
378             return redisTemplate.opsForSet().isMember(key, value);
379         } catch (Exception e) {
380             log.error(key, e);
381             return false;
382         }
383     }
384 
385     /**
386      * 将数据放入set缓存
387      *
388      * @param key    键
389      * @param values 值 可以是多个
390      * @return 成功个数
391      */
392     public long sSet(String key, Object... values) {
393         try {
394             return redisTemplate.opsForSet().add(key, values);
395         } catch (Exception e) {
396             log.error(key, e);
397             return 0;
398         }
399     }
400 
401     /**
402      * 将set数据放入缓存
403      *
404      * @param key    键
405      * @param time   时间(秒)
406      * @param values 值 可以是多个
407      * @return 成功个数
408      */
409     public long sSetAndTime(String key, long time, Object... values) {
410         try {
411             Long count = redisTemplate.opsForSet().add(key, values);
412             if (time > 0)
413                 expire(key, time);
414             return count;
415         } catch (Exception e) {
416             log.error(key, e);
417             return 0;
418         }
419     }
420 
421     /**
422      * 获取set缓存的长度
423      *
424      * @param key 键
425      * @return
426      */
427     public long sGetSetSize(String key) {
428         try {
429             return redisTemplate.opsForSet().size(key);
430         } catch (Exception e) {
431             log.error(key, e);
432             return 0;
433         }
434     }
435 
436     /**
437      * 移除值为value的
438      *
439      * @param key    键
440      * @param values 值 可以是多个
441      * @return 移除的个数
442      */
443     public long setRemove(String key, Object... values) {
444         try {
445             Long count = redisTemplate.opsForSet().remove(key, values);
446             return count;
447         } catch (Exception e) {
448             log.error(key, e);
449             return 0;
450         }
451     }
452 
453     // ============================5-zset=============================
454 
455     /**
456      * 根据key获取Set中的所有值
457      *
458      * @param key 键
459      * @return
460      */
461     public Set<Object> zSGet(String key) {
462         try {
463             return redisTemplate.opsForSet().members(key);
464         } catch (Exception e) {
465             log.error(key, e);
466             return null;
467         }
468     }
469 
470     /**
471      * 根据value从一个set中查询,是否存在
472      *
473      * @param key   键
474      * @param value 值
475      * @return true 存在 false不存在
476      */
477     public boolean zSHasKey(String key, Object value) {
478         try {
479             return redisTemplate.opsForSet().isMember(key, value);
480         } catch (Exception e) {
481             log.error(key, e);
482             return false;
483         }
484     }
485 
486     public Boolean zSSet(String key, Object value, double score) {
487         try {
488             return redisTemplate.opsForZSet().add(key, value, 2);
489         } catch (Exception e) {
490             log.error(key, e);
491             return false;
492         }
493     }
494 
495     /**
496      * 将set数据放入缓存
497      *
498      * @param key    键
499      * @param time   时间(秒)
500      * @param values 值 可以是多个
501      * @return 成功个数
502      */
503     public long zSSetAndTime(String key, long time, Object... values) {
504         try {
505             Long count = redisTemplate.opsForSet().add(key, values);
506             if (time > 0)
507                 expire(key, time);
508             return count;
509         } catch (Exception e) {
510             log.error(key, e);
511             return 0;
512         }
513     }
514 
515     /**
516      * 获取set缓存的长度
517      *
518      * @param key 键
519      * @return
520      */
521     public long zSGetSetSize(String key) {
522         try {
523             return redisTemplate.opsForSet().size(key);
524         } catch (Exception e) {
525             log.error(key, e);
526             return 0;
527         }
528     }
529 
530     /**
531      * 移除值为value的
532      *
533      * @param key    键
534      * @param values 值 可以是多个
535      * @return 移除的个数
536      */
537     public long zSetRemove(String key, Object... values) {
538         try {
539             Long count = redisTemplate.opsForSet().remove(key, values);
540             return count;
541         } catch (Exception e) {
542             log.error(key, e);
543             return 0;
544         }
545     }
546     // ===============================6-list=================================
547 
548     /**
549      * 获取list缓存的内容
550      *
551      * @param key   键
552      * @param start 开始 0 是第一个元素
553      * @param end   结束 -1代表所有值
554      * @return
555      * @取出来的元素 总数 end-start+1
556      */
557     public List<Object> lGet(String key, long start, long end) {
558         try {
559             return redisTemplate.opsForList().range(key, start, end);
560         } catch (Exception e) {
561             log.error(key, e);
562             return null;
563         }
564     }
565 
566     /**
567      * 获取list缓存的长度
568      *
569      * @param key 键
570      * @return
571      */
572     public long lGetListSize(String key) {
573         try {
574             return redisTemplate.opsForList().size(key);
575         } catch (Exception e) {
576             log.error(key, e);
577             return 0;
578         }
579     }
580 
581     /**
582      * 通过索引 获取list中的值
583      *
584      * @param key   键
585      * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
586      * @return
587      */
588     public Object lGetIndex(String key, long index) {
589         try {
590             return redisTemplate.opsForList().index(key, index);
591         } catch (Exception e) {
592             log.error(key, e);
593             return null;
594         }
595     }
596 
597     /**
598      * 将list放入缓存
599      *
600      * @param key   键
601      * @param value 值
602      * @return
603      */
604     public boolean lSet(String key, Object value) {
605         try {
606             redisTemplate.opsForList().rightPush(key, value);
607             return true;
608         } catch (Exception e) {
609             log.error(key, e);
610             return false;
611         }
612     }
613 
614     /**
615      * 将list放入缓存
616      *
617      * @param key   键
618      * @param value 值
619      * @param time  时间(秒)
620      * @return
621      */
622     public boolean lSet(String key, Object value, long time) {
623         try {
624             redisTemplate.opsForList().rightPush(key, value);
625             if (time > 0)
626                 expire(key, time);
627             return true;
628         } catch (Exception e) {
629             log.error(key, e);
630             return false;
631         }
632     }
633 
634     /**
635      * 将list放入缓存
636      *
637      * @param key   键
638      * @param value 值
639      * @return
640      */
641     public boolean lSet(String key, List<Object> value) {
642         try {
643             redisTemplate.opsForList().rightPushAll(key, value);
644             return true;
645         } catch (Exception e) {
646             log.error(key, e);
647             return false;
648         }
649     }
650 
651     /**
652      * 将list放入缓存
653      *
654      * @param key   键
655      * @param value 值
656      * @param time  时间(秒)
657      * @return
658      */
659     public boolean lSet(String key, List<Object> value, long time) {
660         try {
661             redisTemplate.opsForList().rightPushAll(key, value);
662             if (time > 0)
663                 expire(key, time);
664             return true;
665         } catch (Exception e) {
666             log.error(key, e);
667             return false;
668         }
669     }
670 
671     /**
672      * 根据索引修改list中的某条数据
673      *
674      * @param key   键
675      * @param index 索引
676      * @param value 值
677      * @return
678      */
679     public boolean lUpdateIndex(String key, long index, Object value) {
680         try {
681             redisTemplate.opsForList().set(key, index, value);
682             return true;
683         } catch (Exception e) {
684             log.error(key, e);
685             return false;
686         }
687     }
688 
689     /**
690      * 移除N个值为value
691      *
692      * @param key   键
693      * @param count 移除多少个
694      * @param value 值
695      * @return 移除的个数
696      */
697     public long lRemove(String key, long count, Object value) {
698         try {
699             Long remove = redisTemplate.opsForList().remove(key, count, value);
700             return remove;
701         } catch (Exception e) {
702             log.error(key, e);
703             return 0;
704         }
705     }
706 }

四、RedisUtilTest

  1 package com.miaoshaproject;
  2 
  3 import java.io.Serializable;
  4 import java.util.Date;
  5 import java.util.List;
  6 import java.util.Map;
  7 import java.util.Map.Entry;
  8 import java.util.concurrent.LinkedBlockingQueue;
  9 import java.util.concurrent.ThreadPoolExecutor;
 10 import java.util.concurrent.TimeUnit;
 11 
 12 import com.miaoshaproject.util.redis.RedisUtil;
 13 import org.apache.commons.lang3.StringUtils;
 14 import org.junit.AfterClass;
 15 import org.junit.Assert;
 16 import org.junit.BeforeClass;
 17 import org.junit.Ignore;
 18 import org.junit.Test;
 19 import org.junit.runner.RunWith;
 20 import org.springframework.beans.factory.annotation.Autowired;
 21 import org.springframework.boot.test.context.SpringBootTest;
 22 import org.springframework.test.context.junit4.SpringRunner;
 23 
 24 import lombok.Data;
 25 
 26 /**
 27  * @Author wangshuo
 28  * @Date 2022/5/15, 15:34
 29  * Please add a comment
 30  */
 31 
 32 @RunWith(SpringRunner.class)
 33 @SpringBootTest
 34 public class RedisUtilTest {
 35     @Autowired
 36     private RedisUtil redisUtil;
 37 
 38     @BeforeClass
 39     public static void setUpBeforeClass() throws Exception {
 40     }
 41 
 42     @AfterClass
 43     public static void tearDownAfterClass() throws Exception {
 44     }
 45 
 46     /**
 47      * 设置缓存过期时间
 48      *
 49      */
 50     @Test
 51     public void testExpire() throws Exception {
 52         redisUtil.set("aaaKey", "aaaValue");
 53         redisUtil.expire("aaaKey", 100);
 54         Assert.assertEquals(redisUtil.get("aaaKey"), "aaaValue");
 55         TimeUnit.SECONDS.sleep(100);
 56         Assert.assertNotEquals(redisUtil.get("aaaKey"), "aaaValue");
 57 
 58     }
 59 
 60     @Test
 61     public void testGetExpire() throws Exception {
 62         redisUtil.set("aaaKey", "aaaValue");
 63         redisUtil.expire("aaaKey", 100);
 64         // 设置了缓存就会及时的生效,所以缓存时间小于最初设置的时间
 65         Assert.assertTrue(redisUtil.getExpire("aaaKey") < 100L);
 66     }
 67 
 68     @Test
 69     public void testHasKey() throws Exception {
 70         redisUtil.set("aaaKey", "aaaValue");
 71         // 存在的
 72         Assert.assertTrue(redisUtil.hasKey("aaaKey"));
 73         // 不存在的
 74         Assert.assertFalse(redisUtil.hasKey("bbbKey"));
 75     }
 76 
 77     @Test
 78     public void testDel() throws Exception {
 79         redisUtil.set("aaaKey", "aaaValue");
 80         // 存在的
 81         Assert.assertTrue(redisUtil.hasKey("aaaKey"));
 82         redisUtil.del("aaaKey");
 83         Assert.assertFalse(redisUtil.hasKey("bbbKey"));
 84     }
 85 
 86     @Test
 87     public void testGet() throws Exception {
 88         redisUtil.set("aaaKey", "aaaValue");
 89         Assert.assertEquals(redisUtil.get("aaaKey"), "aaaValue");
 90     }
 91 
 92     @Test
 93     public void testSetStringObject() throws Exception {
 94         Assert.assertTrue(redisUtil.set("aaaKey", "aaaValue"));
 95     }
 96 
 97     @Test
 98     public void testSetStringObjectLong() throws Exception {
 99         Assert.assertTrue(redisUtil.set("aaaKeyLong", 100L));
100     }
101 
102     @Test
103     public void testSetObject() {
104         // 测试对象
105         TestModel testModel = new TestModel();
106         testModel.setId(System.currentTimeMillis());
107         testModel.setName("测试");
108         redisUtil.set("testModel", testModel);
109         TestModel testModel2 = (TestModel) redisUtil.get("testModel");
110         System.err.println(testModel2);
111         System.err.println(testModel2.getName());
112         System.err.println(testModel2.getId());
113     }
114 
115     @Test
116     @Ignore
117     public void testIncr() throws Exception {
118         String key = "testIncr";
119         redisUtil.incr(key, 1);
120         redisUtil.expire(key, 10); // 缓存失效10s
121         Assert.assertEquals(redisUtil.get(key), 1);
122     }
123 
124     // 高并发下 递增 测试
125     @Test
126     @Ignore
127     public void testIncr2() throws Exception {
128         // 模拟发送短信的并发
129         // 首先开启一个线程池,创建一个专门消费短信的线程
130         // 一次性放入多个线程实例 ,实例 都是2秒请求一次 ,而10s内的只能允许一条。 也就是说我测试100个线程,只能10s一条
131         ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
132         Thread[] threads = new Thread[100];
133         for (int i = 0; i < 100; i++) {
134             threads[i] = new Thread(new Runnable() {
135                 @Override
136                 public void run() {
137                     try {
138                         TimeUnit.SECONDS.sleep(2);
139                     } catch (InterruptedException e) {
140                         e.printStackTrace();
141                     }
142                     //
143                     String key = "testIncr2_17353620612";
144                     long count = redisUtil.incr(key, 1);
145                     if (count == 1L) {
146                         redisUtil.expire(key, 10); // 缓存失效10s
147                         System.err.println("短信发送成功===" + new Date());
148 
149                     } else {
150                         System.err.println("访问次数快===" + new Date());
151                     }
152                 }
153             });
154             threadPoolExecutor.submit(threads[i]);
155         }
156 
157         while (threadPoolExecutor.getQueue().isEmpty()) {
158             threadPoolExecutor.shutdown();
159             System.err.println("所有线程执行完毕");
160         }
161 
162         System.in.read();// 加入该代码,让主线程不挂掉
163 
164 //        // 启动线程
165 //        for (int i = 0; i < 100; i++) {
166 //            threads[i].start();
167 //        }
168     }
169 
170     long count = 0L;
171 
172     // 高并发下 错误的测试 递增 测试
173     @Test
174     @Ignore
175     public void testIncr3() throws Exception {
176         // 模拟发送短信的并发
177 
178         // 首先开启一个线程池,创建一个专门消费短信的线程
179         // 一次性放入多个线程实例 ,实例 都是2秒请求一次 ,而10s内的只能允许一条。 也就是说我测试100个线程,只能10s一条
180         ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
181         Thread[] threads = new Thread[100];
182         for (int i = 0; i < 100; i++) {
183             threads[i] = new Thread(new Runnable() {
184                 @Override
185                 public void run() {
186 //                    try {
187 //                        TimeUnit.SECONDS.sleep(2);
188 //                    } catch (InterruptedException e) {
189 //                        e.printStackTrace();
190 //                    }
191 //                    pool-3-thread-1count===1
192 //                   pool-3-thread-5count===1
193                     String key = "testIncr2_17353620612";
194                     count = count + 1;
195                     System.err.println(Thread.currentThread().getName() + "count===" + count);
196                     // 督导的count
197                     // if (count == 1L) {
198 //                        count = count - 1;
199 //                        System.err.println("短信发送成功===" + new Date());
200 //                    } else {
201 //                        System.err.println("访问次数快===" + new Date());
202 //                    }
203                 }
204             });
205             threadPoolExecutor.submit(threads[i]);
206         }
207 
208         while (threadPoolExecutor.getQueue().isEmpty()) {
209             threadPoolExecutor.shutdown();
210             System.err.println("所有线程执行完毕");
211         }
212 
213 //        System.in.read();// 加入该代码,让主线程不挂掉
214     }
215 
216     @Test
217     @Ignore
218     public void testDecr() throws Exception {
219         String key = "Decr_17353620612";
220         redisUtil.decr(key, 1);
221         redisUtil.expire(key, 10); // 缓存失效10s
222         Assert.assertEquals(redisUtil.get(key), 1);
223     }
224 
225     @Test
226     public void testHget() throws Exception {
227         redisUtil.hset("testHget", "testHget", "testHget");
228         Assert.assertEquals("testHget", redisUtil.hget("testHget", "testHget"));
229 
230     }
231 
232     @Test
233     public void testHsetStringStringObject() throws Exception {
234         redisUtil.hset("map", "testHsetStringStringObject", "testHsetStringStringObject");
235 
236     }
237 
238     // 测试放在hash 里面的对象
239     @Test
240     public void testHsetObject() {
241         // 测试对象
242         TestModel testModel = new TestModel();
243         testModel.setId(System.currentTimeMillis());
244         testModel.setName("测试");
245         redisUtil.hset("hash", "testModel", testModel);
246         TestModel testModel2 = (TestModel) redisUtil.hget("hash", "testModel");
247         System.err.println(testModel2);
248         System.err.println(testModel2.getName());
249         System.err.println(testModel2.getId());
250     }
251 
252     // 太奇妙了 放进去Long 取出来会根据大小变为相应的数据类型
253     @Test
254     public void testHsetStringStringObjectLong() throws Exception {
255         redisUtil.hset("testHsetStringStringObjectLong", "int", 100); // java.lang.Integer 读取来是inter
256         System.err.println(redisUtil.hget("testHsetStringStringObjectLong", "int").getClass().getTypeName());
257 //        Assert.assertEquals(redisUtil.hget("map", "testHsetStringStringObject"), 100L);
258         redisUtil.hset("testHsetStringStringObjectLong", "long", System.currentTimeMillis()); // java.lang.Integer 读取来是inter
259         System.err.println(redisUtil.hget("testHsetStringStringObjectLong", "long").getClass().getTypeName());
260 
261     }
262 
263     @Test
264     public void testHdel() throws Exception {
265         redisUtil.hset("testHdel", "int", 100);
266         Assert.assertEquals(redisUtil.hget("testHdel", "int"), 100);
267         redisUtil.hdel("testHdel", "int");
268         Assert.assertEquals(redisUtil.hget("testHdel", "int"), null);
269 
270     }
271 
272     @Test
273     public void testHHasKey() throws Exception {
274         redisUtil.hset("testHHasKey", "int", 100);
275         Assert.assertTrue(redisUtil.hHasKey("testHHasKey", "int"));
276 
277     }
278 
279     @Test
280     public void testHincr() throws Exception {
281         System.err.println(redisUtil.hincr("testHincr", "testHincr", 1));
282 
283     }
284 
285     @Test
286     public void testHdecr() throws Exception {
287         System.err.println(redisUtil.hincr("testHincr", "testHincr", 1));
288     }
289 
290     @Test
291     public void testSGet() throws Exception {
292         redisUtil.sSet("testSGet", "testSGet1");
293         redisUtil.sSet("testSGet", "testSGet2");
294         System.err.println(StringUtils.join(redisUtil.sGet("testSGet"), ","));
295     }
296 
297     @Test
298     public void testSHasKey() throws Exception {
299         redisUtil.sSet("testSHasKey", "testSHasKey");
300         Assert.assertTrue(redisUtil.sHasKey("testSHasKey", "testSHasKey"));
301 
302     }
303 
304     @Test
305     public void testSSet() throws Exception {
306         redisUtil.sSet("testSSet", "testSSet");
307 
308     }
309 
310     @Test
311     public void testSSetAndTime() throws Exception {
312         redisUtil.sSetAndTime("testSSetAndTime", 20, "testSSetAndTime1");
313         redisUtil.sSetAndTime("testSSetAndTime", 5, "testSSetAndTime2");
314         System.err.println(StringUtils.join(redisUtil.sGet("testSSetAndTime"), ","));
315         TimeUnit.SECONDS.sleep(5);
316         System.err.println(StringUtils.join(redisUtil.sGet("testSSetAndTime"), ","));
317         TimeUnit.SECONDS.sleep(20);
318         System.err.println(StringUtils.join(redisUtil.sGet("testSSetAndTime"), ","));
319 
320     }
321 
322     @Test
323     public void testSGetSetSize() throws Exception {
324         redisUtil.sSetAndTime("testSGetSetSize", 20, "testSGetSetSize1");
325         redisUtil.sSetAndTime("testSGetSetSize", 5, "testSGetSetSize");
326         Assert.assertEquals(redisUtil.sGetSetSize("testSGetSetSize"), 2);
327     }
328 
329     @Test
330     public void testSetRemove() throws Exception {
331         redisUtil.sSetAndTime("testSetRemove", 20, "testSetRemove1");
332         redisUtil.sSetAndTime("testSetRemove", 5, "testSetRemove");
333         Assert.assertEquals(redisUtil.sGetSetSize("testSetRemove"), 2);
334         redisUtil.setRemove("testSetRemove", "testSetRemove");
335         Assert.assertEquals(redisUtil.sGetSetSize("testSetRemove"), 1);
336 
337     }
338 
339     @Test
340     public void testLGet() throws Exception {
341         redisUtil.lSet("testLGet", "testLGet0", 10); // 10秒过期
342         redisUtil.lSet("testLGet", "testLGet1", 10);
343         // 查询三个元素 2-0+1
344         List<Object> list = redisUtil.lGet("testLGet", 0, 2);
345         System.err.println("list===" + list);
346         // 查询两个
347         List<Object> list2 = redisUtil.lGet("testLGet", 0, 1);
348         System.err.println("list2===" + list2);
349         // 查询全部
350         List<Object> list3 = redisUtil.lGet("testLGet", 0, -1);
351         System.err.println("list3===" + list3);
352 
353     }
354 
355     @Test
356     public void testLGetListSize() throws Exception {
357         // 看看重复元素会怎么处理
358         long size = 0;
359         redisUtil.lSet("testLGetListSize", "testLGetListSize0", 10); // 10秒过期
360         size = redisUtil.lGetListSize("testLGetListSize");
361         System.err.println(size);
362         redisUtil.lSet("testLGetListSize", "testLGetListSize0", 10);
363         size = redisUtil.lGetListSize("testLGetListSize");
364         System.err.println(size);
365     }
366 
367     //
368     @Test
369     public void testLGetIndex() throws Exception {
370         redisUtil.lSet("testLGetIndex", "testLGetIndex0", 10); // 10秒过期
371         redisUtil.lSet("testLGetIndex", "testLGetIndex1", 10);
372         Object obj = redisUtil.lGetIndex("testLGetIndex", 0);
373         Assert.assertEquals(obj, "testLGetIndex0");
374     }
375 
376     @Test
377     public void testLSetStringObject() throws Exception {
378         redisUtil.lSet("testLSetStringObject", "testLSetStringObject0");
379         redisUtil.lSet("testLSetStringObject", "testLSetStringObject1");
380         redisUtil.lSet("testLSetStringObject", "testLSetStringObject2");
381     }
382 
383     @Test
384     public void testLSetStringObjectLong() throws Exception {
385 
386     }
387 
388     @Test
389     public void testLUpdateIndex() throws Exception {
390         redisUtil.lSet("testLUpdateIndex", "testLUpdateIndex0");
391         redisUtil.lSet("testLUpdateIndex", "testLUpdateIndex1");
392         redisUtil.lSet("testLUpdateIndex", "testLUpdateIndex2");
393         Object obj = redisUtil.lUpdateIndex("testLUpdateIndex", 0, "更新的");
394         Assert.assertEquals("更新的", obj);
395     }
396 
397     @Test
398     public void testLRemove() throws Exception {
399         redisUtil.lSet("testLRemove", "testLRemove0");
400         redisUtil.lSet("testLRemove", "testLRemove1");
401         redisUtil.lSet("testLRemove", "testLRemove2");
402         Object obj = redisUtil.lRemove("testLRemove", 1, "testLRemove2");
403     }
404 
405     @Data
406     class TestModel implements Serializable {
407         /**
408          * @Fields serialVersionUID : (用一句话描述这个变量表示什么)
409          */
410         private static final long serialVersionUID = 1L;
411         private Long id;
412         private String name;
413     }
414 }