Redis的基本使用

2023-05-16

Redis简介

什么是Redis

Redis是一款开源的内存数据库,也称为键值存储(database)、缓存(database)和消息队列(database)系统。它提供了丰富的数据结构和高效的操作方式,并且支持多种编程语言的客户端,如Java、Python、C++等,让开发人员可以轻松地使用Redis来构建高性能、可扩展的应用程序。Redis支持数据持久化、主从复制、Lua脚本等特性,并且广泛应用于Web应用、实时计算、日志分析、消息发布等场景。

什么是Jedis

Jedis是Redis官方推荐的Java连接Redis的客户端库,提供了丰富的API和易于使用的接口,使得Java开发人员能够轻松地与Redis进行交互。Jedis支持连接池、集群、管道和事务等特性,在高并发,高吞吐量的场景下,提供了性能优秀和稳定可靠的解决方案。Jedis在Redis社区得到了广泛的应用和支持,是Java开发人员使用Redis的首选客户端库之一。
以下是一个简单的使用Jedis连接Redis服务器,并执行一些Redis操作的例子:

import redis.clients.jedis.Jedis;

public class Example {

   public static void main(String[] args) {

      // 创建一个Jedis对象,用于与Redis服务器交互
      Jedis jedis = new Jedis("localhost", 6379);

      // 执行一些Redis命令

      // 存储一个字符串值
      jedis.set("key1", "value1");

      // 获取一个字符串值
      String value = jedis.get("key1");
      System.out.println(value);

      // 存储一个哈希映射
      jedis.hset("hash1", "field1", "value1");

      // 获取一个哈希映射的所有字段和值
      System.out.println(jedis.hgetAll("hash1"));

      // 关闭Jedis对象
      jedis.close();
   }
}

什么是Spring Data Redis

Spring Data Redis是Spring Data项目家族中的一个子项目,它通过简化和抽象操作,简化了在Redis中存储和访问数据的过程。它提供了丰富的API和基于注解的配置,使得Java开发人员能够更加便捷地与Redis交互,而无需过多地关注低级别的Redis操作。Spring Data Redis支持散列、列表、集合、有序集合等丰富的数据结构,同时也支持事务操作、消息发布订阅、Lua脚本执行、持久化等特性。通过Spring Data Redis,Java开发人员能够快速地搭建和运行分布式和高并发的应用程序。

spring-data-redis针对jedis提供了如下功能:

  1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类,提供了许多方法,包括以下几种类型的方法:
  • 对字符串的操作方法:如opsForValue().set、opsForValue().get等方法。
  • 对哈希的操作方法:如opsForHash().put、opsForHash().get等方法。
  • 对列表的操作方法:如opsForList().leftPush、opsForList().rightPop等方法。
  • 对集合的操作方法:如opsForSet().add、opsForSet().members等方法。
  • 对有序集合的操作方法:如opsForZSet().add、opsForZSet().range等方法。
  • 事务操作方法:如multi、watch、exec等方法。
  • 管道操作方法:如executePipelined()方法。
  • 异步操作方法:如opsForValue().setAsync、opsForHash().getAsync等方法。
  • 发布订阅操作方法:如convertAndSend()方法、subscribe()方法等。

除此之外,RedisTemplate还提供了对键、连接、序列化等方面的控制和操作的方法,如delete()、getConnectionFactory()、setKeySerializer()等方法。总之,RedisTemplate提供了丰富的方法,使得Java开发者可以轻松地使用Redis。

  1. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口:
  • ValueOperations:简单K-V操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:针对map类型的数据操作
  • ListOperations:针对list类型的数据操作
  1. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即:
  • BoundKeyOperations:
  • BoundValueOperations
  • BoundSetOperations
  • BoundListOperations
  • BoundSetOperations、
  • BoundHashOperations
  1. 将事务操作封装,有容器控制。
  2. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)
    JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。
    StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
    JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】

RedisTemplate中API使用

首要配置

引入pom.xml依赖

<!--Redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

添加配置文件

# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000ms

RedisTemplate的用法

  • 首先使用@Autowired注入RedisTemplate(后面直接使用,就不特殊说明)
@Autowired
private RedisTemplate redisTemplate;

KEY操作

//    删除key
redisTemplate.delete(key);
//    删除多个key
redisTemplate.delete(keys);
//    指定key的失效时间
redisTemplate.expire(key,time,TimeUnit.MINUTES);
//    根据key获取过期时间
Long expire = redisTemplate.getExpire(key);
//    判断key是否存在
redisTemplate.hasKey(key);

String类型相关操作

/**	添加缓存	**/
//1、通过redisTemplate设置值
redisTemplate.boundValueOps("StringKey").set("StringValue");
redisTemplate.boundValueOps("StringKey").set("StringValue",1, TimeUnit.MINUTES);
//2、通过BoundValueOperations设置值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
stringKey.set("StringVaule");
stringKey.set("StringValue",1, TimeUnit.MINUTES);
//3、通过ValueOperations设置值
ValueOperations ops = redisTemplate.opsForValue();
ops.set("StringKey", "StringVaule");
ops.set("StringValue","StringVaule",1, TimeUnit.MINUTES);

/**	设置过期时间	**/
redisTemplate.boundValueOps("StringKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("StringKey",1,TimeUnit.MINUTES);

/**	获取缓存值	**/
//1、通过redisTemplate设置值
String str1 = (String) redisTemplate.boundValueOps("StringKey").get();
//2、通过BoundValueOperations获取值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
String str2 = (String) stringKey.get();
//3、通过ValueOperations获取值
ValueOperations ops = redisTemplate.opsForValue();
String str3 = (String) ops.get("StringKey");

/**	删除key	**/
Boolean result = redisTemplate.delete("StringKey");
/**	顺序递增	**/
redisTemplate.boundValueOps("StringKey").increment(3L);
/**	顺序递减	**/
redisTemplate.boundValueOps("StringKey").increment(-3L);

Hash类型相关操作

/**	添加缓存	**/
//1、通过redisTemplate设置值
redisTemplate.boundHashOps("HashKey").put("SmallKey", "HashVaue");
//2、通过BoundValueOperations设置值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
hashKey.put("SmallKey", "HashVaue");
//3、通过HashOperations设置值
HashOperations hashOps = redisTemplate.opsForHash();
hashOps.put("HashKey", "SmallKey", "HashVaue");
/**	设置过期时间	**/
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("HashKey",1,TimeUnit.MINUTES);
/**	添加一个Map集合	**/
HashMap<String, String> hashMap = new HashMap<>();
redisTemplate.boundHashOps("HashKey").putAll(hashMap );
/**	提取所有的field	**/
//1、通过redisTemplate获取值
Set keys1 = redisTemplate.boundHashOps("HashKey").keys();
//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Set keys2 = hashKey.keys();
//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
Set keys3 = hashOps.keys("HashKey");
/**	提取所有的value值	**/
//1、通过redisTemplate获取值
List values1 = redisTemplate.boundHashOps("HashKey").values();
//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
List values2 = hashKey.values();
//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
List values3 = hashOps.values("HashKey");
/**	根据key提取value值	**/
//1、通过redisTemplate获取
String value1 = (String) redisTemplate.boundHashOps("HashKey").get("SmallKey");
//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
String value2 = (String) hashKey.get("SmallKey");
//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
String value3 = (String) hashOps.get("HashKey", "SmallKey");
/**	获取所有的键值对集合	**/
//1、通过redisTemplate获取
Map entries = redisTemplate.boundHashOps("HashKey").entries();
//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Map entries1 = hashKey.entries();
//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
Map entries2 = hashOps.entries("HashKey");
/**	删除	**/
//删除小key
redisTemplate.boundHashOps("HashKey").delete("SmallKey");
//删除大key
redisTemplate.delete("HashKey");
/**	判断Hash中是否含有该值	**/
Boolean isEmpty = redisTemplate.boundHashOps("HashKey").hasKey("SmallKey");

Set类型相关操作

/**	添加Set缓存	**/
//1、通过redisTemplate设置值
redisTemplate.boundSetOps("setKey").add("setValue1", "setValue2", "setValue3");
//2、通过BoundValueOperations设置值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
setKey.add("setValue1", "setValue2", "setValue3");
//3、通过ValueOperations设置值
SetOperations setOps = redisTemplate.opsForSet();
setOps.add("setKey", "SetValue1", "setValue2", "setValue3");
/**	设置过期时间	**/
redisTemplate.boundValueOps("setKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("setKey",1,TimeUnit.MINUTES);
/**	根据key获取Set中的所有值	**/
//1、通过redisTemplate获取值
Set set1 = redisTemplate.boundSetOps("setKey").members();
//2、通过BoundValueOperations获取值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
Set set2 = setKey.members();
//3、通过ValueOperations获取值
SetOperations setOps = redisTemplate.opsForSet();
Set set3 = setOps.members("setKey");
/**	根据value从一个set中查询,是否存在	**/
//1、通过redisTemplate获取值
Boolean isEmpty = redisTemplate.boundSetOps("setKey").isMember("setValue2");
/**	获取Set缓存的长度	**/
Long size = redisTemplate.boundSetOps("setKey").size();
/**	移除指定的元素	**/
Long result1 = redisTemplate.boundSetOps("setKey").remove("setValue1");
/**	移除指定的key	**/
Boolean result2 = redisTemplate.delete("setKey");
###	LIST类型相关操作
/**	添加缓存	**/
//1、通过redisTemplate设置值
redisTemplate.boundListOps("listKey").leftPush("listLeftValue1");
redisTemplate.boundListOps("listKey").rightPush("listRightValue2");
//2、通过BoundValueOperations设置值
BoundListOperations listKey = redisTemplate.boundListOps("listKey");
listKey.leftPush("listLeftValue3");
listKey.rightPush("listRightValue4");
//3、通过ValueOperations设置值
ListOperations opsList = redisTemplate.opsForList();
opsList.leftPush("listKey", "listLeftValue5");
opsList.rightPush("listKey", "listRightValue6");
/**	将List放入缓存	**/
ArrayList<String> list = new ArrayList<>();
redisTemplate.boundListOps("listKey").rightPushAll(list);
redisTemplate.boundListOps("listKey").leftPushAll(list);
/**	设置过期时间(单独设置)	**/
redisTemplate.boundValueOps("listKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("listKey",1,TimeUnit.MINUTES);
/**	获取List缓存全部内容(起始索引,结束索引)	**/
List listKey1 = redisTemplate.boundListOps("listKey").range(0, 10); 
/**	从左或从右弹出一个元素	**/
String listKey2 = (String) redisTemplate.boundListOps("listKey").leftPop();  //从左侧弹出一个元素
String listKey3 = (String) redisTemplate.boundListOps("listKey").rightPop(); //从右侧弹出一个元素
/**	根据索引查询元素	**/
String listKey4 = (String) redisTemplate.boundListOps("listKey").index(1);
/**	获取List缓存的长度	**/
Long size = redisTemplate.boundListOps("listKey").size();
/**	根据索引修改List中的某条数据(key,索引,值)	**/
redisTemplate.boundListOps("listKey").set(3L,"listLeftValue3");
/**	移除N个值为value(key,移除个数,值)	**/
redisTemplate.boundListOps("listKey").remove(3L,"value");

Zset类型的相关操作

/**	向集合中插入元素,并设置分数	**/
//1、通过redisTemplate设置值
redisTemplate.boundZSetOps("zSetKey").add("zSetVaule", 100D);
//2、通过BoundValueOperations设置值
BoundZSetOperations zSetKey = redisTemplate.boundZSetOps("zSetKey");
zSetKey.add("zSetVaule", 100D);
//3、通过ValueOperations设置值
ZSetOperations zSetOps = redisTemplate.opsForZSet();
zSetOps.add("zSetKey", "zSetVaule", 100D);
/**	向集合中插入多个元素,并设置分数	**/
DefaultTypedTuple<String> p1 = new DefaultTypedTuple<>("zSetVaule1", 2.1D);
DefaultTypedTuple<String> p2 = new DefaultTypedTuple<>("zSetVaule2", 3.3D);
redisTemplate.boundZSetOps("zSetKey").add(new HashSet<>(Arrays.asList(p1,p2)));
/**	按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部	**/
Set<String> range = redisTemplate.boundZSetOps("zSetKey").range(0, -1);
/**	获得指定元素的分数	**/
Double score = redisTemplate.boundZSetOps("zSetKey").score("zSetVaule");
/**	返回集合内的成员个数	**/
Long size = redisTemplate.boundZSetOps("zSetKey").size();
/**	返回集合内指定分数范围的成员个数(Double类型)	**/
Long COUNT = redisTemplate.boundZSetOps("zSetKey").count(0D, 2.2D);
/**	返回集合内元素在指定分数范围内的排名(从小到大)	**/
Set byScore = redisTemplate.boundZSetOps("zSetKey").rangeByScore(0D, 2.2D);
/**	带偏移量和个数,(key,起始分数,最大分数,偏移量,个数)	**/
Set<String> ranking2 = redisTemplate.opsForZSet().rangeByScore("zSetKey", 0D, 2.2D 1, 3);
/**	返回集合内元素的排名,以及分数(从小到大)	**/
Set<TypedTuple<String>> tuples = redisTemplate.boundZSetOps("zSetKey").rangeWithScores(0L, 3L);
  for (TypedTuple<String> tuple : tuples) {
      System.out.println(tuple.getValue() + " : " + tuple.getScore());
  }ss
/**	返回指定成员的排名	**/
//从小到大
Long startRank = redisTemplate.boundZSetOps("zSetKey").rank("zSetVaule");
//从大到小
Long endRank = redisTemplate.boundZSetOps("zSetKey").reverseRank("zSetVaule");
/**	从集合中删除指定元素	**/
redisTemplate.boundZSetOps("zSetKey").remove("zSetVaule");
/**	删除指定索引范围的元素(Long类型)	**/
redisTemplate.boundZSetOps("zSetKey").removeRange(0L,3L);
/**	删除指定分数范围内的元素(Double类型)	**/
redisTemplate.boundZSetOps("zSetKey").removeRangeByScorssse(0D,2.2D);
/**	为指定元素加分(Double类型)	**/
Double score = redisTemplate.boundZSetOps("zSetKey").incrementScore("zSetVaule",1.1D);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis的基本使用 的相关文章

  • C++程序设计实践指导——第一章 简单编程 (1)

    第一章 简单编程 xff08 1 xff09 1 1删除序列中相同的数 有16个数 1 2 2 3 4 4 5 6 6 7 8 8 8 9 xff0c 10 xff0c 10 xff0c 已按由小到大的顺序排好 存储 在数组a中 试建立一个
  • 模板template的使用

    函数模板应用实例 C 43 43 与C的不同点 xff1a 模板template的使用 include lt iostream gt 无需加上 34 h 34 using namespace std 使用命名空间 template lt t
  • 时间复杂度与空间复杂度

    时间复杂度与空间复杂度 1 Running time xff1a 时间复杂度 T n 61 O f n 时间复杂度 xff1a 算法执行时间随规模增大而增长的趋势 以算法中重复执行的次数作为算法时间复杂度的依据 计算机科学中 xff0c 算
  • 对抗样本是怎么产生的?如何避免对抗攻击?

    全文共2637字 xff0c 预计学习时长5分钟 图片来源 xff1a pexels 64 pixabay 随着深度神经网络的出现 xff0c 机器学习领域的安全问题日益突出 人们对神经网络的可解释性提出了质疑 xff0c 也自然对深度学习
  • 数组与指针的区别

    数组与指针的区别 1 指针数组与数组指针 int a1 3 It is an array each element is a pointer int a2 3 It is a pointer It points to an array wi
  • while/do while/for/goto的区别

    Calculate 1 43 2 43 3 43 43 100
  • if/switch的区别

  • Function pointer and pointer function指针函数和函数指针

    指针函数 int f int x int y pointer function f is a function it returns a pointer 函数指针 int f int x int y function pointer f i
  • 类的应用示例+继承

    类的应用示例 include lt iostream gt using namespace std 使用命名空间 class student constructor initializer list 构造函数初始化列表 public stu
  • Structure and Class (结构体与类)

  • STL中vector的使用

    STL中vector vector的使用 include lt iostream gt include lt vector gt using namespace std 使用命名空间 int main vector lt int gt v1
  • Fibonacci的四种求解方法

    Fibonacci Sequence的使用 include lt iostream gt using namespace std 使用命名空间 T N 61 O N 2 61 T N 1 43 T N 2 43 2 int fib2 int
  • 最大子序列和问题

    最大子序列和问题Maximum Subsequence Sum include lt iostream gt include lt vector gt using namespace std 使用命名空间 T N 61 O N 3 Cubi
  • C++基础之基础

    C 43 43 xff08 容纳了好几种编程范式 xff09 xff1a 面向对象编程 泛型编程 过程化编程 面向对象编程 xff1a 其本质是以建立模型体现出来的抽象思维过程和面向对象的方法 抽象 继承 多态 xff1a 抽象性是指将具有
  • 这五大MySQL在线课程,最适合初学者的你!

    全文共3214字 xff0c 预计学习时长7分钟 图片来源 xff1a pexels com 64 pixabay 过去几年 xff0c 有句话越来越流行 xff1a 人人必须学习如何编码 这值得鼓励 在当今以信息和技术为中心的世界里 xf
  • 课程作业(单链表C++实现)

    单链表的操作C 43 43 实现 include lt iostream gt using namespace std 使用命名空间 template lt typename dataType gt 定义一个数据类型模板 class lin
  • 课程作业(二叉查找树)

    mainTest cpp include lt iostream gt include 34 binarySearchTree h 34 using namespace std int main cout lt lt 34 请按前序输入一棵
  • C++程序设计实践指导——第一章 简单编程 (2)

    第一章 简单编程 xff08 2 xff09 1 9 统计与替换字符串中的关键字 建立一个类WordNum xff0c 统计一个英文字符串中的英文单词个数 字符串中的各英文单i司以一个或多个空格分隔 如字符串 34 I am a stude
  • STL+Python+图像处理-学习资源

    1 C 43 43 STL学习网站 CPlusPlus com CppReference com gcc gnu org 2 Python学习书籍及网站 Python Crash Course Learn Python the Hard W
  • STL----------C++Primer(笔记)

    1 string string word cin gt gt word getline cin word 关系操作符 lt lt 61 gt gt 61 include lt cctype gt 头文件 string s 61 34 Hel

随机推荐

  • 侯捷-STL与泛型编程(GP)笔记

    1 stl体系结构基础介绍 分配器 xff08 allocator xff09 xff1a 主管分配内存 适配器 xff08 adaptor xff09 xff1a 进行一个转换 xff0c 与另一个对象绑定 include lt iost
  • 课程作业——数据结构与算法C++(1)

    课程作业6 xff08 归并排序 冒泡排序 插入排序 选择排序 xff09 归并排序 冒泡排序 插入排序 选择排序 主程序 include lt iostream gt include lt vector gt using std vect
  • C++程序设计实践指导——第二章 样例讲解

    复数计算器 include lt iostream gt include lt cmath gt include lt string gt include lt fstream gt include lt ctime gt using na
  • 步进电机控制与LCD显示L297与L298

    步进电机控制与LCD显示L297与L298 上次介绍了PWM和L298结合的电机调速 xff01 接下来介绍L297与L298结合的例子 xff01 PWM电机调速 下面是L297的简介 xff1a L297是步进电机专用控制器 xff0c
  • 变分自编码器(一):原来是这么一回事

    https kexue fm archives 5253 过去虽然没有细看 xff0c 但印象里一直觉得变分自编码器 xff08 Variational Auto Encoder xff0c VAE xff09 是个好东西 于是趁着最近看概
  • Linux 安装npm

    1 root 登录linux 2 cd usr loacl node 没有目录就自己创建一个 3 wget https npm taobao org mirrors node v4 4 7 node v4 4 7 linux x64 tar
  • DE1-SOC开发笔记

    verilog FPGA 采用verilog开发语言 xff0c 使用时序和组合逻辑 进行行为 xff0c 数据流 xff0c 结构建模 RTL级编程 xff0c 在实际板卡上面验证逻辑的正确性 sopc xff1a 软硬件结合的开发方式
  • 关于立创EDA使用的几点心得

    对于立创EDA 与AD仅为小白 xff0c 仅布过简单的双层板 xff0c 以下仅记录自己的几点心得 1 如果想要在立创商城 xff0c 嘉立创实现打板贴片一体化 xff0c 采用的普遍的两种方法 xff1a 立创EDA xff0c 有在线
  • 《当下即是生活》季羡林——读书笔记

    目录 书籍简介 经典摘录 三思而行 满招损 xff0c 谦受益 牵就与适应 睁一只眼 闭一只眼 论压力 论恐惧 难得糊涂 春色满寰中 槐花 书籍简介 作者季羡林 本书精选季羡林关于人生活法的散文 xff0c 阐述一个人怎样活在当下 xff0
  • Python装饰器

    Python的装饰器 decorator 可以说是Python的一个神器 xff0c 它可以在不改变一个函数代码和调用方式的情况下给函数添加新的功能 Python的装饰器同时也是Python学习从入门到精通过程中必需要熟练掌握的知识 小编我
  • Python学习笔记--带参数的装饰器

    带参数的装饰器 装饰器的副作用柯里化functools带参数的装饰器多参数小结 装饰器的副作用 def fn 39 39 39 this is fn 39 39 39 help fn 结果 xff1a Help on function fn
  • 六、51单片机之定时器/计数器_理论

    1 什么是定时器 计数器 定时器就是单片机设定一个时间间隔 xff0c 时间间隔到后通知单片机 例如设置100ms的定时器 xff0c 100ms后定时器通知单片机时间到了 1 定时器是单片机的一种内部外设 以前的单片机只有CPU 也就是只
  • 八、51单片机之蜂鸣器

    1 蜂鸣器的原理 蜂鸣器分为有源蜂鸣器和无源蜂鸣器 这里的 源 不是指电源 xff0c 而是指震荡源 1 1 无源蜂鸣器 1 早期蜂鸣器都是无源的 2 内部没有震荡电路 xff0c 无源蜂鸣器比有源蜂鸣器更便宜 3 无源蜂鸣器内部没有震荡源
  • CSS3实现loading效果

    前言 晚上躺床上刷视频的时候看到有个前端大佬写了一个loading xff0c 这是效果 xff1a loading 感觉也挺有意思哈 xff0c 要不自己也写一个 xff0c 学习 43 复习 两不误 但是又因为太晚了 xff0c 不想起
  • C#应用程序界面开发基础——窗体控制(2)——MDI窗体

    MDI窗体 单文档界面 xff08 SDI xff09 多文档界面 xff08 MDI xff09 MDI窗体的概念 MDI窗体 xff08 Multiple Document Interface xff0c 多文档界面 xff09 用于同
  • windows 10 + GTX1650 环境下基于TensorFlow的深度学习环境配置

    因论文需要 xff0c 简单的记录一个深度学习环境的配置过程 说明 xff1a 与广为应用的基于Anaconda的深度学习环境配置方法不同的是 xff0c 本文直接基于Python基础环境 43 Pycharm进行环境的配置 xff0c 不
  • TX2硬盘扩展

    TX2硬盘扩展 硬件平台 xff1a NVIDIA TX2 Samsung SSD 860EVO 系统平台 xff1a Ubuntu 18 04 LTS 安装 将硬盘连接至侧边SATA接口 扩展home 1 查看硬盘所有分区 sudo fd
  • Android手机4G网络设置ipv6

    我的卡是联通的 xff0c 所以下面截图也是联通的 xff0c 移动和电信的卡类似 xff1b 1 进入目录 xff1a 设置 移动网络 接入点名称 xff08 APN xff09 xff1b 2 点击默认的连接项 xff0c 进入详情页
  • 简单TCP编程

    1 TCP服务端 span class token macro property span class token directive hash span span class token directive keyword include
  • Redis的基本使用

    Redis简介 什么是Redis Redis是一款开源的内存数据库 xff0c 也称为键值存储 database 缓存 database 和消息队列 database 系统 它提供了丰富的数据结构和高效的操作方式 xff0c 并且支持多种编