- 博客(21)
- 收藏
- 关注
原创 定时器的两种实现方式(优先级队列&时间轮)
时间轮是一个存储定时任务的环形队列, 它的底层采用数组实现, 数组中的每个元素可以存放一个任务列表 (TimerTaskList), 任务列表是一个环形的双向链表, 这个链表的每一个元素都是一个定时任务项 (TimerTaskEntry), 其中封装了真正的定时任务 (TimerTask), 即真正要执行的任务.一个基础的时间轮如下图所示.
2023-10-07 16:45:00 1096 1
原创 redis 哨兵
redis 主从复制模式下, 一旦主节点出现故障, 不能提供服务的时候, 就需要人工进行主从切换. 这是十分不靠谱的, 毕竟谁也不知道主节点什么时候出现故障, 这样就无法第一时间恢复服务. 所以 redis 从 2.8 版本开始提供了 哨兵(Redis Sentinel) 模式, 可以通过自动化手段来解决主节点出现故障的问题.
2024-04-06 23:03:59 1263
原创 redis 主从复制
可用性问题: 如果这台机器挂了, 服务就中断了.性能瓶颈: 单台机器的性能以及并发量是比较有限的.所以, 引入分布式系统主要就是为了解决上面的问题以使用 redis 的视角来看, 往往希望有多个程序来部署 redis 服务, 从而构建出一个 redis 集群, 此时就可以让这个集群给整个分布式系统中的其它服务提供更稳定, 更高效的服务.在若干个 redis 节点中, 有的是 “主” 节点, 有的是 “从” 节点, 从节点上的数据要和主节点的数据保持一致.
2024-04-05 00:11:21 1072 1
原创 redis 事务
当用户执行 WATCH 命令的时候, 这组被执行的 key 在该客户端中会被监控. 在真正提交事务的时候, 会判定当前这个 key 的版本号与当初 WATCH 的时候的版本号是否一致, 如果不一致, 说明这个 key 在其它客户端中被修改过了, 此时就直接丢弃事务中的操作.每次添加一个操作的时候, 都会提示 “QUQUQD”, 说明这个操作已经进入到客户端的队列中了, 真正执行 exec 的时候, 客户端才会把上述的操作发送给服务器, 服务器根据这个队列中的操作依次执行.
2024-03-28 22:11:23 675 1
原创 redis 持久化
众所周知, redis 是一个内存数据库, 会把数据存入内存中, 但是内存中的数据是不持久的, 当服务器重启之后, redis 上次存入内存的数据就消失了. 所以为了保证应用程序的可用性, 就需要让 redis 服务器中的数据持久化保存.所谓的持久化, 就是把数据存入硬盘中, 这样下来, 即使 redis 服务器重启了, 也可以从硬盘中读取数据, 保证数据的持久性.
2024-03-28 00:12:00 943 1
原创 Java 文件操作 -- File 类 及 IO 流
在程序创建出流对象的时候, 就会在进程 PCB 中的文件描述符表中申请一个空间, 里面记录了打开文件的信息, 而关闭文件则会释放这块空间. 如果不手动释放这块空间, 并且程序长时间运行时需要不停地对很多文件进行操作, 文件描述符很快就会被占满, 被占满之后这个程序就打不开新的文件了, 这样程序就会抛出异常. 所以当文件使用完毕之后, 应该习惯性的关闭文件.写入文件的时候, 不能保证文件实时的写入到硬盘中, 所以就需要在写入操作完成之后使用 flush 方法刷新缓冲区, 保证数据的实时写入。
2023-11-26 23:40:04 885 1
原创 阻塞队列 (BlockingQueue)
说到队列, 第一时间想到的队列的特性就是: 一种 “先进先出” 的数据结构而阻塞队列是一种特殊的队列, 也继承了队列的特性: 先进先出.但是在其先进先出的特性的基础上, 阻塞队列拥有另一种特殊的功能, 顾名思义, 就是:阻塞它在普通队列的基础上额外拥有以下几个特性:如果队列为空, 执行出队列的操作, 就会阻塞, 阻塞到另一个线程往里面添加元素为止 (队列不空)如果队列满了, 执行入队列的操作, 也会阻塞, 阻塞到另一个线程从里面取走元素为止 (队列不满)
2023-11-25 21:29:07 846
原创 单例模式详解
当两个线程都在 instance 对象没创建的时候去调用 getInstance() 方法, 如果线程 t1 调用方法的时候, t2 在 t1 未 save 的情况下也调用了这个方法, 那么两个线程读取到寄存器中的 instance 值都为空, 那么两个线程都会进行 new 操作, 这样这个单例类就会创建出来两个实例了, 违背了单例模式的初衷.多线程操作单例类, 只会调用 getInstance() 方法, 只要判断 getInstance() 方法是否是线程安全的, 那么使用的时候就是安全的.
2023-11-24 22:29:30 830 1
原创 volatile wait notify
在计算机的视角中, load 和 cmp 这两个操作所执行的速度相对比, load 的速度会慢非常多, 由于 load 执行的速度太慢了, 再加上反复 load 多次的结果都是一样的, 这时 JVM 就做出一个大胆的决定: 它判定没人会修改 flag 变量的值, 就不再进行重复 load 的操作了, 干脆只读取一次就好…在多线程环境下, 线程最大的问题就是: 抢占式执行, 随机调度. 所以各个线程之间执行的顺序就是由操作系统来调度的, 但是在实际开发中, 往往需要让程序按照指定的顺序进行运行.
2023-11-23 23:55:49 934
原创 线程的状态和线程安全问题
拓展:TERMINATED 状态有什么用吗?其实 TERMINATED 状态并没有什么实际意义上的作用, 只是起到了一个标识的作用.在 Java 中, 之所以存在 TERMINATED 状态是因为迫不得已, Java 中有着对象的生命周期这个规则, 但是这个规则与系统内核中的线程并非一致. 所以内核中的线程释放的时候, 并不能保证 Java 中的代码中的 Thread 对象也立即被释放.
2023-11-14 09:30:00 75
原创 Java 线程的创建和使用
其中 start() 方法是创建了一个线程, 由新的线程来执行 run() 方法. 上述使用创建线程来打印的操作与 main 方法中直接打印的区别就是: 如果只是 main 方法直接打印, 那么打印的操作就是 Java 进程中调用 main 方法的进程来打印的. 通过 t.start(), 本质就是主线程调用了 t.start() 创建出了一个新线程, 新的线程调用了 t.run() 中的打印. 当 run 方法执行完毕, 这个线程就自动销毁了.线程: 线程是进程中的一个执行单元, 是程序执行的基本单位.
2023-08-09 09:00:00 438 2
原创 泛型的定义、使用及其擦除机制
在 Java 编程思想中, 有这样一句对泛型介绍的话: 一般的类和方法, 只能使用具体的类型: 要么是基本类型, 要么是自定义的类. 如果要编写可以应用于多种类型的代码, 这种刻板的限制对代码束缚就会很大.于是为了解决这样的一个问题, 在 JDK1.5 中就引入了一种新的语法, 那就是泛型. 泛型在代码层面上就是对类型实现了参数化.
2023-06-26 22:42:52 243 1
原创 HTTP协议 -- HTTP协议数据报文
到这就是基本的 HTTP 的报文解读了, 其中重要的就是请求报文和响应报文, 下图是整体的 HTTP 交互结构。
2023-03-11 21:05:01 578
原创 IP 协议
NAT 要求, 所有的公网 IP 必须是唯一的. 私网 IP 在不同的局域网中是可以重复出现的, 私网里的设备想要访问公网的设备, 就必须对应的的 NAT 设备(路由器), 把 IP 地址进行映射, 从而能访问到公网的设备. 反之, 公网的设备不能直接访问私网的设备, 而且不同局域网中的设备是无法相互访问的.子网掩码使用 32 比特位来对应 IP 地址中的每一位, 如果为 1, 就代表是网络号, 为 0, 就代表是主机号. 子网掩码的左侧都为1, 代表网络号, 右侧都为 0, 代表主机号.
2023-03-04 21:49:10 364
原创 TCP协议(3) -- TCP中内部重要的核心工作机制(2)
TCP 协议在这就已经完结了, 其中第二和第三节讲了 TCP 中的核心机制, 但是 TCP 中不止这 10 个机制, 而是因为这 10 个机制是比较重要的机制, 所以进行着重讲解.
2023-02-24 21:03:51 130
原创 TCP协议(2) -- TCP中内部重要的核心工作机制
所以, 网络上的数据后发先至也是同理, 两个主机之间进行通讯, 所构成通讯的路径就相当于上面的迷宫一样, 可能存在多条到达目的地址的路线, 两条数据所经过的 路由器 / 交换机 的性能也可能存在差异, 有的转发数据报的速率快, 有的转发的慢, 由此, 两个数据包到达的时间就存在变数了, 这是一种非常普遍的情况…所以, 只有在接收方对发送方断开连接的请求发送的 ack 和 接收方断开连接的请求(也就是上图的2 和 3) 发送的时机相同, 才能够合并成一个包, 如果时机不相同, 就合并不了了.
2023-02-18 11:29:30 506 1
原创 TCP协议(1) -- 认识TCP协议段格式
这里举一个例子来了解一下端口号:先来了解一下服务器端口 (目的端口)假如, 有一天, 我不想当程序猿了, 我想改行, 做一名厨师… 为了实现我这个梦想, 我就去了某个大学的食堂, 在这个食堂的第 2 餐厅, 第 12 号窗口, 开了一家北京烤鸭店(此处, 第 2 餐厅, 就相当于我的服务器的 IP 地址, 第 12 号窗口, 就相当于我在这个 IP 地址里的一个端口号)
2023-02-17 23:29:42 970
原创 顺序表详解及基本实现
线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列…线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。顺序表作为一种简单的数据结构, 其中必然会出现一些小问题1. 顺序表中间/头部的插入删除,时间复杂度为O(N)2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗.
2022-10-31 23:23:24 439 7
原创 C语言实现三子棋
通过二维数组与循环这两个简单的知识来实现三子棋一共有两个源文件和一个头文件,将三个文件放在一个工程里test.c#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"//菜单void Menu(){ printf("********************************\n"); printf("********* 0.Exit *******\n"); printf("********* 1.Pl
2022-05-10 21:34:11 265
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人