自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(21)
  • 收藏
  • 关注

原创 数据结构-AVL树

但是AVL树虽然保证了查询的效率,但是还是有一些机制上的问题,比如说,旋转非常消耗时间,比如我们在单旋的时候已经进行了8步操作,这只是其中的一次插入,当数据大量插入的时候AVL树显然是不够用的,因此科学家们又引入了红黑树的机制。AVL树它本质上其实还是一个二叉树,它的特点符合二叉树的所有特点,在此之外,AVL树还具有平衡的性质,也就是说,它的左子树和右子树的高度差的绝对值不会大于1,因此这样也就保证了AVL树的查找效率。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。

2024-06-04 22:39:16 764 1

原创 HashMap实现原理

有的人可能会问,哈希值怎么可能相同,那么此时我们需要明白一个道理,很简单,鸽巢原理:可以概括为一句话,假如我们有10个鸽巢,11个鸽子,那么此时必定至少有一个鸽巢内的鸽子数是大于两个的。5.如果该位置为链表,那么就会遍历链表,然后让新的hash值和原来的链表长度按位与,如果值为0那么新表的位置也为原来的位置,否则就是原来的位置加原来的数组容量,比如原来是3位置存储,大小为16,那么新的位置就是19。3.如果是存在,那么直接覆盖,如果不存在,那么就会判断该位置是否为红黑树,走红黑树的添加逻辑。

2024-05-24 12:39:42 506 1

原创 Redis机制-主从模式、哨兵模式、分片集群

Redis中提供的集群方案一共有三种方式主从复制哨兵模式分片集群。

2024-05-22 09:00:00 1472

原创 Redis机制-Redis互斥锁、分布式锁

如上图,执行add1( )时,Thread1第一次加锁时,value会被改成1,当add2( )想获取锁时,此时Redis会进行判断,你是不是线程1来的,发现add2( )的线程名为Thread1,那么此时该锁可以重入的,value值会变成2,当add2( )执行完以后,释放锁,value又变为1,add1( )执行完以后,value变成0,此时的锁才是真正被线程1所释放了。如图,当8080的线程1进行访问时,其余的端口和线程都不可以进行访问,此时就达到了分布式锁的效果,有效的解决了超卖问题。

2024-05-21 19:41:45 1145

原创 Redis机制-Redis双写一致性、持久化、数据删除策略、数据淘汰策略

可以看到,这种操作在线程1删除缓存之后,线程2这时刚好插入进来(因为线程是独立进行的),线程2查询缓存未命中之后,然后查库进行了更新操作,又把缓存恢复为10,但是线程1执行完之后数据库变为了20,此时就会出现脏数据的现象。如图:当线程1查询数据库之后得到了数据10,但是还没来得及写回到缓存的时候,线程2进行了数据库的更新,并且删除了缓存,此时线程1将10写入了缓存,又造成了缓存数据库不一致的情况,又出现了脏数据。为了保证双写一致性,提出了延时双删的逻辑,主要是为了让主从模式的数据库能够进行数据的同步。

2024-05-21 09:00:00 623

原创 Redis机制-Redis缓存穿透,击穿,雪崩理解等问题的理解和学习

图1 正常的Redis缓存流程。

2024-05-20 21:57:58 1153

原创 Java网络编程之https协议和证书(加密传输+三把钥匙+证书确认)

所以这件事是一个很麻烦的事情。第三部分:Body是空行之后的内容,如果服务器返回了一个html那么html就会在body中,就像上图的乱码一样(这是有用的信息,只不过需要对信息进行解密,所以显示出来是乱码)。Body:是http请求的第三部分,在空行之后的内容都是Body,如果Body存在的话,那么在Header中会有一个Content-Length属性来表示Body的长度。由上图可以看出,当密钥被黑客解惑时,此时黑客也知道了密文的具体内容,所以要保证安全传输,密钥的传输也必须使用加密传输。

2024-03-19 22:52:24 1267 1

原创 Java网络编程原理之TCP协议

在以上的这些机制之外,TCP还有面向字节流的特性,缓冲区特性和大小限制的特性。TCP是保证可靠性的传输层的网络协议。

2024-03-17 23:28:55 769 1

原创 JavaEE初阶多线程(五)-内存可见性、原子性、线程等待

这段代码在flag之前加了volatile关键字,使得该每次 t1线程在读取flag的时候都会从主内存中拿出flag变量来进行while循环的判断。在上一篇文章中,我们大概介绍了Java线程在内存中是如何对数据进行读取的,为了适应不同的硬件设备和编译器,Java对内存中使用了“工作内存”这个概念。工作内存会在主内存中取出要操作的变量,然后操作完成之后会对主内存的该变量进行更新。的时候,会从主内存中读取volatile变量修饰的最新值到工作内存中,然后从工作内存中读取该变量的副本。就能保证内存可见性。

2024-03-08 12:00:00 978 1

原创 JavaEE初阶(四)-synchronized关键字-监视器锁

这是加了synchronized的锁,因为可重入,所以并不会锁死,在该代码中的synchronized加锁对象是该类中的this,因为是同一把锁。synchronized本质上是要修改指定对象的对象头,从使用的角度来看,synchronized也需要搭配一个具体的对象来使用。第一段代码使用当前实例对象作为锁对象,意味着每一个实例对象都有自己的锁资源,不同实例之间的锁是独立的,不会相互干扰。虽然其他线程都会等待这个线程释放锁,但是当其释放了锁之后,其余线程也会争抢这把锁,不遵循先来后到的原则。

2024-03-07 10:18:27 528 1

原创 JavaEE多线程初阶(三)线程状态和线程安全

可以看到,当主线程sleep时间短的时候,主线程执行到while循环的时候,t 线程的执行还没有完成,因此t.isAlive()返回的结果为true,所以可以打印出RUNNABLE这个状态。当t1读取的值为5000时,t2同时也读取到了5000这个值,都自加1以后就变成了5001,但是此时将其返回以后,还是5001这个值,却并不是5002,因此也就存在两次加1但是实际上只加了1次的行为,因此会发生线程安全的问题。想象一下,当多个人要进入一个房间时,如果没有任何的保证机制,A进入房间之后,还没有出来;

2024-03-06 12:00:00 937 1

原创 JavaEE初阶多线程(二)-Thread基础

以上就是Java多线程中所需要注意到的一部分基础操作,包括Thread的构造方法和属性,以及启动线程中标志位如何设置,还有中断线程,让线程等待的时候如何使用 Join()方法。下一篇文章还会继续更新Java多线程操作所需要注意到的一些基本内容。

2024-03-04 12:00:00 862 1

原创 JavaEE多线程(一)

设想一下如果我们要去超市买东西,需要购买洗发水,面包和鱼三种生活用品,但是这些生活用品在超市的不同楼层,如果我们是一个人去逛超市,那么就需要将这三个地方分别跑一趟,但是这个时候,如果有朋友或者家人和我们一同前去,那么只需要分别去这三个地方就可以了,相当于是三个人分别完成了不同的事务,但是本质上这三个人都是为了逛超市购买商品这一件事情进行服务的。说的通俗一点,一个进程是由多个线程所组成的,并且这些线程是共享同一份资源的。,该线程必须等待Thread的对象执行完自己线程的代码以后才可以执行接下来的代码。

2024-03-02 22:16:14 397

原创 Java类和对象(二)

this引用指向当前的对象,在成员方法中对所有该类中的成员变量都是通过this引用完成实现的。而this引用的是调用成员方法的对象。可以将代码修改如下:System.out.println(this.year+"年"+this.month+"月"+this.day+"日");可以看到 setDate方法中无缘无故多了个Date 类型的this参数,但是在实例化的对象调用该方法的时候却并没有传入this参数的具体值,结果是编译通过且并无报错,程序正常运行。

2023-11-27 10:21:58 55

原创 Java类和对象(一)

面向对象是解决问题之间的一种思想,主要依靠对象之间的交互来完成一件事情。在程序设计中,面向对象的程序始终关注的是对象,并且对象往往是现实中所存在的实体。比如说洗衣机,汽车等等。对于计算机来说,其并不认识洗衣机与汽车,所以在程序编写的过程中就可以使用面向对象的编程语言来对洗衣机和汽车进行描述。在Java中定义类需要用到class关键字,具体的定义语法如下所示// 创建类field;// 字段(属性) 或者 成员变量method;// 行为 或者 成员方法其中field。

2023-11-26 17:43:20 31 1

原创 c语言指针(二)

以上这段代码是可以运行的,当pc为char*时,&pc指向为char*类型的指针,ppc也为指向char*类型的指针,而arr是char*类型的指针数组,取其数组名也为指向char*类型的指针变量。在以前的学习中,我们知道数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,那么我们能把函数的地址放在数组之中,从而可以在数组中找到函数的地址,找到该函数吗?对于test函数,其返回值为void 参数为无参状态,而要定义能够接收该函数的指针只需要将指针也定义为该函数相同的类型即可,如上代码所示。

2023-11-17 09:00:00 55

原创 c语言指针(一)

数组指针本质上还是指针,相比于之前的整型指针和字符指针,那么数组指针就是能够指向数组的指针。接下来先分辨以下行代码,到底哪个是数组指针。第一行是一个指针数组,它声明了一个名为p1的数组,其中包含10个整形指针元素。每个元素指向一个int类型的变量。这里的p1是一个由指针组成的数组。第二行是数组指针,因为[ ]的优先级是高于*的,p先和*结合意味着p是一个指针,然后指向一个10个大小的整型数组,叫做数组指针。

2023-11-16 11:08:16 39 2

原创 内存函数操作详解

从char型的数组中可能看不出来差距,但是在int型的数族中可以看出arr2中取得1384在赋值到arr1之中时变成了104,这是因为以字节为单位进行的拷贝,只会改变内存,而打印输出的时候,会根据打印的类型一次读取4个字节,由于拷贝时数据的缺失,所以没法打印出原本的1384。从而造成了丢失的现象。其运行结果为0,原因是其比较了前13个字节因为第13个字节存储的是都是04,所以比较出的结果大小是一样的。情况2,&src>&dest,应当从前往后拷贝,比如3覆盖了2,紧接着4覆盖了3,从而也可以实现拷贝。

2023-11-06 20:04:29 117 6

原创 自创qsort函数实现任意类型的数据排序

参数size的数据类型也是size_t,其代表的是待排序数据中一个元素的大小,比如排一个int类型的数据,那么size就为4,如果是char,那么size取值为1。具体来说,int (*compar)(const void*, const void*)表示一个指向函数的指针,该函数接受两个const void*类型的参数,并返回一个int类型的值。参数为char *buf1和char *buf2,使用指针来对所选的数值一个字节一个字节的调换(具体内存中指针对不同的类型的数据是如何操作的可以看。

2023-11-01 18:51:55 50 6

原创 数据在内存中的存储

c语言中一些基本的数据类型有char字符型(整数族)short短整型(整数族)int整型(整数族)long长整型(整数族)long long长长整型(整数族)float单精度浮点型(浮点族)double双精度浮点型(浮点族)struct构造类型(自定义)指针类型(int char folat)而字符型在内存中存储的方式是该字符的ASCII码值,又因为ASCII码值是整数,所以字符型存储模式属于整数族。

2023-10-28 17:32:25 55 8

原创 c语言实现三子棋游戏

三子棋小游戏

2023-10-12 20:42:42 63 9

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除