自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

子时已过的博客

技术驱动世界

  • 博客(51)
  • 收藏
  • 关注

原创 Unity面向切面编程

AOP:面向切面编程

2024-04-18 12:07:33 349

原创 主线程捕获子线程异常

正常情况下使用多线程出现异常时,都是按照单个任务去处理异常,在线程间不需要通信的情况下,任务之间互不影响,主线程也不必知道子线程是否发成异常。但是在某些复杂业务中,多个线程在执行过程中如果出现异常需要反馈给主线程,所以需要在子线程出现异常时通知主线程。那么只需要处理子线程异常即可。

2024-04-15 16:23:39 242

原创 Operation is not supported on this platform.

Operation is not supported on this platform.

2024-04-11 14:23:13 238

原创 OutOfMemoryError异常

除了程序计数器外,虚拟机内存在其他几个运行时区域都有发生OutOfMemoryError异常的可能。

2022-05-03 13:10:30 1173

原创 垃圾收集器与内存分配策略

程序计数器、虚拟机栈、本地方法栈三个区域随着线程的创建而创建、执行完成销毁,栈中的栈帧随着放大的进入和退出执行入栈与出栈,每个栈帧分配多少内存基本上是在类结构确定下来时已知,因此这几个区域的内存分配与回收都具备确定性。

2022-05-02 11:07:22 269

原创 JAVA内存区域

JAVA虚拟机在执行JAVA程序的过程中会把它所管理的内存划分为若干个不同的内存区域。

2022-05-01 09:49:01 210

原创 JVM虚拟机类加载机制(二)

类加载器虽然用于实现类的加载动作,但是它在Java程序中起到的作用不只是类加载阶段。对于任意一个类,都需要由加载它的类加载器和类本身一同确立其在Java虚拟机中的唯一性。

2022-04-30 10:06:45 224

原创 JVM虚拟机类加载机制(一)

类从被加载到虚拟机内存中开始,到卸载出内存截止,整个生命周期包括:加载、验证、准备、解析,初始化、使用、卸载七个阶段。其中验证、准备、解析三个部分统称为连接。

2022-04-10 13:28:01 994

原创 .net 使用Docker开发

.net 使用Docker开发

2022-04-09 19:37:42 1908

原创 函数式数据结构-列表

在开始之前我们先了解几个名词:1、什么是函数式编程:函数式编程属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用,可以说是面向过程的程序设计。2、函数式编程的优势:函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。易于"并发编程" 。函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。3、什么是函数式数据结构:函数式数据结构只能被纯函数操作,纯函数一定不能修改原始数据结构或者产生副作用。函数式数据结构被定义为不可变的。

2021-01-12 08:38:46 292

原创 多线程那点事—Parallel.for

先看段代码:for (int i = 0; i < 10; i++){ Task.Factory.StartNew(()=>Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} ~ {i}"));}从代码上可以看出我们预期是打印1~10,但实际的打印结果是:7 ~ 104 ~ 1010 ~ 109 ~ 104 ~ 103 ~ 105 ~ 109 ~ 106 ~ 108 ~ 10与预期的不一

2021-01-02 19:24:09 613 1

原创 函数式编程-记忆化缓存

记忆化,是一种为了提高应用程序性能的FP技术。程序加速是通过缓存函数的结果实现的,避免了重复计算带来的额外开销。1、现在我们使用Dictionary作为缓存结构public static Func<T, R> Memoize<T, R>(Func<T, R> func) where T : IComparable{ Dictionary<T, R> cache = new Dictionary<T, R>(); r

2021-01-01 20:39:15 271 1

原创 C#数据结构-赫夫曼树

什么是赫夫曼树?赫夫曼树(Huffman Tree)是指给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小。哈夫曼树(也称为最优二叉树)是带权路径长度最短的树,权值较大的结点离根较近。public class HNode<T>{ public HNode() { data = default(T); weight = 0; leftNode = null; rightNode = nul

2020-12-19 21:02:18 342 2

原创 C#数据结构-线索化二叉树

为什么线索化二叉树?对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树。现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱、后继,便于快速查找树的前驱后继。不多说,直接上代码:/// <summary>/// 线索二叉树 节点/// </summary>/// <typeparam name="T"></typeparam>public class ClueTreeNode&lt

2020-12-16 21:08:05 158

原创 C#数据结构-二叉树-链式存储结构

对比上一篇文章“顺序存储二叉树”,链式存储二叉树的优点是节省空间。二叉树的性质:1、在二叉树的第i层上至多有2i-1个节点(i>=1)。2、深度为k的二叉树至多有2k-1个节点(k>=1)。3、对任何一棵二叉树T,如果其终结点数为n0,度为2的节点数为n2,则n0=n2+1。4、具有n个节点的完全二叉树的深度为log2n+1。5、对于一棵有n个节点的完全二叉树的节点按层序编号,若完全二叉树中的某节点编号为i,则若有左孩子编号为2i,若有右孩子编号为2i+1,母亲节点为i/2。在此记

2020-12-06 16:05:00 386

原创 C#数据结构-二叉树-顺序存储结构

什么是二叉树:每个树的节点只有两个子树的树形结构。为什么使用顺序存储结构:使用数组存放满二叉树的各结点非常方便,可以根据一个结点的索引号很容易地推算出它的双亲、孩子、兄弟等结点的编号,从而对这些结点进行访问,这是一种存储二叉满二叉树或完全二叉树的最简单、最省空间的做法。 /// <summary>/// 顺序存储二叉树/// </summary>public class SequentialStorageBinaryTree<T>{ /// <

2020-12-05 20:59:55 269 1

原创 DataTable 将一列转为List

c# linq用起来特方便,因此我们习惯性的用list来操作,这里我们将 DataTable 一列转为List:List<T> homeworkIdList = (from r in dataTable.AsEnumerable() select r.Field<T>("列名")).ToList<T>();

2020-12-03 09:09:38 977

原创 字符串匹配—KMP算法

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n) 。实现方式就不再这里献丑了,网上很多讲解,此处只是记录下c#实现的代码。public class KMP{ public

2020-11-23 08:39:53 165

原创 JAVA正则校验IP地址

if(!Pattern.compile("\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b").matcher(ip).matches()){ System.o.

2020-11-06 10:01:31 505 1

原创 C#数据结构-线程安全队列

什么是线程安全?答:线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。前面几篇写的线性结构,在多线程并行的情况下会出现共享数据会线程间读取与写入不一直的情况,为了解决这种情况,通常会使用锁来解决,也就是将并行改为串行。但是在使用穿行违背了使用多线程并发的初衷,这种情况下我们可以考虑采用线程安全结构。先看下线程安全队列的用法:ConcurrentQueue<i

2020-10-30 08:10:05 957

原创 C#数据结构-HASHSET

命名空间:System.Collections.Generic先看一下官方说明:类提供了高级的设置操作。集是不包含重复元素的集合,其元素无特定顺序。HashSet 对象的容量是对象可以容纳的元素数。当向对象添加元素时,HashSet 对象的容量会自动增加。HashSet<String> hashSet = new HashSet<string>();hashSet.Add("test");hashSet.Add("test");Console.WriteLine(hash

2020-10-24 18:08:00 796

原创 C#番外篇-SpinWait

SpinWait封装常见旋转逻辑。在单处理器计算机上,始终使用 “生成” 而不是 “繁忙等待”,在装有超线程技术的 Intel 处理器的计算机上,这有助于防止硬件线程不足。SpinWait 封装了一种很好的旋转和真正的生成。SpinWait是一个值类型,这意味着低级别代码可以使用 SpinWait,而不必担心不必要的分配开销。SpinWait 对于普通应用程序通常不起作用。在大多数情况下,应使用由 .NET Framework 提供的同步类,如 Monitor 。但在需要自旋等待的大多数情况下, Spin

2020-10-23 16:22:01 1712 7

原创 C#数据结构-队列

队列作为线性表的另一个数据结构,只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。先来看下用法: Queue queue = new Queue(); queue.Enqueue(1); queue.Enqueue(2); queue.Enqueue(3); queue.Enqueue(4); foreach (va

2020-10-21 08:52:17 179

原创 C#数据结构-链栈

上一篇我们通过数组结构实现了栈结构(准确的说是栈的顺序存储结构),现在我们通过链(单链)存储栈,也就是链栈。通常对于正向单链表来说,是从头节点开始,在链的尾部附加节点,前一个节点的指针指向附加节点;对于实现栈结构来说是在栈顶(链尾部)插入节点,指针指向上一个节点,所以实现栈结构的链可以说是反向单链表。public class LinkStackNode<T>{ /// <summary> /// 数据存储 /// </summary>

2020-10-15 16:45:17 268

原创 C#数据结构-栈

栈的定义不需要多说,相信大家都非常熟悉,但是,在实际应用中栈的应用我们很少想到会去用栈结构,先上代码看下用法: Stack st = new Stack(); st.Push('A'); st.Push('B'); st.Push('C'); st.Push('D'); foreach (char c in st) { Console.Write(c + " "); } Console.WriteLine(); st.Push('E'); foreac

2020-10-14 14:06:03 225

原创 C#数据结构-静态链表

对于双向链表中的节点,都包括一个向前、向后的属性器用于指向前后两个节点,对于引用类型,对象存储的是指向内存片段的内存指针,那么我们可以将其简化看作向前向后的两个指针。现在我们将引用类型替换为值类型int,将链用数组代替,向后的指针替换为数组的下标,那么此时的链我们称为静态链表(或者说是单向静态链表)。不多说,直接上代码(代码已做注解) public class Node<T> { public T data { get; set; } publi

2020-10-13 13:03:41 108

原创 C#数据结构-双向链表

链表的概念以及链表与数组的差异不做过多的叙述,相信大家都耳熟能详,这里以c#语言实现简单的双向链表,作为备用,记录下~ public class Node<T> { private Node<T> prev; private Node<T> next; private T val; public Node<T> Prev { get { return prev; } set {

2020-10-11 19:26:18 342

原创 C# 学习笔记(二)——IL初探

继续学习IL代码,现在我们看下常用的属性器到底是怎么执行的:C#代码如下:using System;namespace ConsoleApp1{ public class MyClass { public MyClass(int v) { val = v; } private int val { get; set; } public int GetVal() {

2020-07-16 08:11:07 374

原创 C# 学习笔记(一)——VS开发汇编准备

做开发有几年了,一直忙于开发各种项目,熟悉并学习各种框架、语言的应用。虽说当今互联网大爆发,各种优秀的语言、技术更迭非常快,只学习应用都不一定跟得上脚步,但是我觉得将一门语言吃透还是很有必要的——毕竟技术是学不完的。不废话先搭建开发环境(vs 开发 汇编——为学习IL做准备):1、安装visual studo 2019,并安装c++ 开发模块。2、配置 vs 高亮显示代码。(在扩展中搜索安装asmDude)效果:3、创建一个空的project4、添加一个c++文件并修改后缀名为.asm:

2020-07-09 08:44:37 412

原创 DOTNET CORE MVC (一)

以控台的形式,运行.net core mvc 代码,Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>();//指定网络主机要使用的启动类型。 });返回默认的IHostBuilder ,程序初始化。根据官方说明文档:该方法做了这么多事情:将 ContentRootPath .

2020-07-03 08:12:38 206

原创 Redis学习笔记(四) 跳跃表与整数集合

(一)跳跃表跳跃表是一种有序的数据结构,它通过每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。Redis使用跳跃表作为有序集合键的底层实现之一,如果一个有序集合包含的元素数量比较多,或者有序集合中元素的成员是比较长的字符串时,Redis就会使用跳跃表作为有序集合键的底层实现。Redis中的两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构。Redis的跳跃表由zskiplistNode 与 zskiplist 两个结构定义。其中zskiplistNod

2020-06-28 12:42:21 128

原创 Redis学习笔记(三) 字典

Redis的字典使用哈希表作为底层实现,一个哈希表中可以有多个哈希表节点,而每个哈希节点就保存在字典中的一个键值对。redis字典所用的哈希表由disht结构定义。typedef struct dictht{ dictEntry **table;//哈希表数组 unsigned long size;//哈希表大小 unsigned long sizemask;//哈希表大小掩码,用于计算索引值 ,总是等于size -1 unsigned long used;//该哈希表已

2020-06-21 10:40:03 132

原创 Redis学习笔记(二) 链表

链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。redis中链表应用广泛,如list中就使用了链表。每一个链表节点使用listNode结构标识(双向链表):typedef struct listNode{ //前置节点 struct listNode *prev; //后置节点 struct listNode *next; //节点值 void *value;}链表大家都熟悉不做过多说明,再看下l

2020-06-16 08:19:42 121

原创 Redis 学习笔记(一) 字符串 SDS

SDS 简单动态字符串。SDS的结构:struct sdshdr{ int len;//记录BUF数组中已使用字节的数量 ,等于SDS所八寸字符串的长度 int free;//记录BUF数组中未使用字节的数量 char buf[];//字节数组,用于保存字符串}1、与c语言的字符串相比,SDS获取长度时,时间复杂度位O(1),c的复杂度位O(n)。2、杜绝缓冲区溢出,c字符串若未重新分配内存,在进行字符串拼接时,会导致扩展字符串s1的数据溢出到s2所在的空间,导致s2所保存的内容被

2020-06-15 08:36:28 732

原创 Redis学习笔记(二十一) 事务

文章开始啰嗦两句,写到这里共21篇关于redis的琐碎知识,没有过多的写编程过程中redis的应用,着重写的是redis命令、客户端、服务器以及生产环境搭建用到的主从、哨兵、集群实现原理,如果你真的能看的进去,相信对你在以后用到redis时会有一定的帮助。写到现在,redis相关的内容暂时告一段落了,以后可能更着重的去介绍c#相关的知识,包括用到IL、.net core底层、微服务等知识。哎呀,写着写着突然又想啰嗦几句,最近几年c#在国内式微java如日中天,好多微软系的小伙伴或者各路大神都不看好c#,

2020-06-13 23:04:17 157

原创 Redis学习笔记(二十) 发布订阅(下)

当一个客户端执行SUBSCRIBE命令订阅某个或某些频道时,这个客户端与被订阅频道之间就建立起了一种订阅关系。Redis将所有频道的订阅关系保存在服务器状态的pubsub_channels字典里面,这个字典的键是某个被订阅的频道,而键的值是一个链表,链表里面记录了所有订阅这个频道的客户端:struct redisServer{ //保存所有频道的订阅关系 dict *pubsub_channels;}如果频道已经有其他的订阅者,那么他在pubsub_channels字典中必然有相

2020-06-12 23:11:42 126

原创 Redis学习笔记(十九) 发布订阅(上)

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息,它的发布与订阅功能由PUBLISH、SUBSCRIBE、PSUBSCRIBE等命令组成。通过执行SUBSCRIBE命令,客户端可以订阅一个或多个频道,从而成为这些频道的订阅者:每当有其他客户端向被订阅的频道发送消息时,频道的所有订阅者都会收到这条消息。偷个懒今天模拟下发布订阅的过程。首先启动6379端口的服务端:然后通过redis-cli命令启动三个客户端,其中两个分别执行subscri

2020-06-11 22:19:48 112

原创 Redis学习笔记(十八) 集群(下)

复制和故障转移Redis集群中的节点分为主节点(master)和从节点(slave),其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制 的主节点下线时,代替下线主节点继续处理命令请求。设置从节点:CLUSTER REPLICATE < node_id >可以让接收命令的节点称为node_id 所指定节点的从节点,并开始对主节点进行复制。1)接收到该命令的节点首先会在自己的clusterState.nodes字典中找到node_id所对应节点的clusterNode结构,并将自

2020-06-10 22:34:22 243

原创 Redis学习笔记(十七) 集群(上)

Redis集群是Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移操作。一个Redis集群通常由多个节点组成,在刚开始的时候每个节点都是相互独立的,他们处于一个只包含自己的集群当中,我们通过使用CLUSTER MEET命令将节点连接到一起,构成一个包含多节点的集群。集群的数据结构:clusterNode结构保存了一个节点的当前状态,比如节点创建时间、节点名称、节点当前的配置纪元、节点的ip端口。每个节点都会使用一个clusterNode结构记录自己的状态,并为集群中的所

2020-06-09 22:50:09 124

原创 Redis学习笔记(十六) Sentinel(哨兵)(下)

身体偶感不适,消失了一段时间,我又回来啦。不多说,继续把哨兵看完。检测主观下线状态默认情况下,Sentinel会以每秒一次的频率向所有与他创建了命令连接的实例(主从服务器以及其他Sentinel)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。实例对PING命令的回复可以分为两种情况:有效回复:实例返回+PONG、-LOADING、-MASTERDOWN三种回复的其中一种。无效回复:实例返回除+PONG、-LOADING、-MASTERDOWN三种回复之外的回复或者规定时间内

2020-06-08 22:34:54 125

空空如也

空空如也

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

TA关注的人

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