自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 TCP的socket的API

TCP处理连接中接收请求的当遇到空白符的时候才会读取完毕,使用这个scanner直接收到的就是字符串,如果使用inputstream的read()方法还需要将字节转化为字符串,客户端在发送请求的时候,必须在每个请求的末尾加上空白符,这个要求是程序员之间通信细节的约定,TCP是按照字节的方式来进行传输的,实际上我们希望若干个字节能构成一个应用层的数据报,区分一个应用层的数据报就是通过空白符来进行分割。等待客户端发送请求,服务器与客户端建立连接之后,返回一个socket对象,如果没有客户端发送请求就会阻塞。

2024-07-24 11:58:39 756

原创 网络编程套接字

UDP数据报套接字编程socket的api在操作系统中,本身就有socket这样的概念,是对于操作系统socket概念的封装,系统中的socket可以理解成是一种文件(视为"网卡"的抽象表现形式,针对socket对文件进行读写操作,就相当于针对网卡这个硬件设备进行读写),文件是一个广义的概念包含很多硬件设备和软件资源针对UDP数据报的一个抽象表示,一个DatagramPacket就相当于是一个UDP数据报,一次发送/接收,就是传输了一个DatagramPacket对象。

2024-07-22 16:34:08 647

原创 初识网络基础知识

此时已经拥有了应用层数据包,把QQ程序调用操作系统的api,应用层要把数据交给传输层(操作系统内核提供api,socket api),传输层拿到应用层数据包之后,就会把这个数据包进行进一步的封装,构造出传输层数据包,此时传输层典型协议有两个TCP,UDP,此处假设使用UDP作为传输协议,UDP报头中存储着一些固定的属性比如发送人和接收人的端口号,后半部分是UDP数据包的载荷。假设QQ的应用层协议是这样的,四个信息分别是发送人,接收人的账号和发送时间及正文,中间用,分开,使用\n作为结束标志,

2024-07-20 16:53:24 527

原创 Java文件IO操作知识点

I:input输入 O:output输出,这是一套人为规定的规则,下面这个图方便我们理解输入输出的定义,统一以CPU为基准在操作系统中其实把很多的资源都抽象成文件,我们在这里所说的文件就是"狭义"文件,平时保存在硬盘上的文件,文件夹也是一种文件,我们称之为目录文件,在硬盘上存储着很多文件和目录,目录之间又存在这一套嵌套关系,这整个结构是一个树形结构N叉树,

2024-07-18 17:56:19 526

原创 多线程进阶

策略也可以理解为做法,策略比较抽象,当这个锁在加锁/解锁遇到锁冲突的时候该去怎么做。

2024-07-15 14:36:21 794

原创 Java中多线程经典案例

相反懒汉模式则会引起线程不安全,因为懒汉模式是在有需要的时候才会去实例化对象,在多线程编程中懒汉模式要进行读和写操作,这一修改变量的值不是原子的,所有会造成线程不安全的问题,因此我们要使用synchronized对读和写操作进行加锁,打包成一个原子的操作,加锁会影响性能的问题,如果是第一次判断instance是否为空则需要加锁,若后续第二次...等,每次加锁都势必会影响性能问题,因此我们可以考虑在加一个if判断。

2024-07-08 10:57:58 568

原创 线程的等待通知机制

此时就会成功阻塞等待,当执行到wait操作时,在wait内部会先解锁,此时object这个锁其他线程是可以获取到的,wait释放锁之后会休息自己不参与调度,把机会让给别人,什么时候开始执行,此时就需要notify()方法,跟wait()配合使用,其他线程通过使用notify将wait唤醒,使用notify的线程必须跟使用wait的线程锁是同一把锁.t2把t1唤醒之后,并不能立即执行,t1需要重新获取锁,由于此时t2还没有结束,t1无法获取到锁被阻塞,所以需要等到t2释放锁以后,t1才能继续执行。

2024-06-29 08:48:40 270

原创 线程安全问题

由于线程是随即调度,抢占式执行,=>这样的随机性就会使程序的执行顺序产生变数,=>不同的结果,有的时候对于这个不同的结果我们是可以接受的,但是有的时候是不可以接受的,我们认为这是bug(只要与需求不符合的就算是bug,)多线程代码,引起的bug,这样的问题就是线程安全问题,存在线程安全问题的代码,称为线程不安全。显然是不可以的,因为我们可以优化load操作是因为在上述循环中每次都load操作的值都是相同的,而这每次的IO操作的值都是不一样的,

2024-06-28 18:17:49 878

原创 关于多线程

如果有多个线程在一个进程中,每个线程都会有自己的状态,优先级,记账信息,上下文,每个都会各自独立在CPU上调度执行,同一个进程中的这些线程,共用同一份系统资源,线程比进程更轻量,主要在于,创建线程省去了"分配资源"的过程,销毁线程也省去了"释放资源"的过程,一旦创建进程就会创建线程,系统就会分配资源,后续创建第二个第三个线程的时候,就不会再重新分配资源了.所谓的进程,在系统中,是通过PCB结构体来描述的,也是通过链表的形式连接起来的,对于系统中,线程,同样也是通过PCB来描述的(Linux)

2024-06-09 10:47:11 699

原创 关于计算机是如何工作的

2.频率:cpu的运算速度,使用频率来描述,可以理解成一秒钟执行多少个指令(机器语言(二进制)=>汇编语言(单词符号),最终都要翻译成cpu上执行的二进制指令),CPU的频率会根据任务量的多少进行调整,不同的cpu支持的指令是不同的,x86/arm的指令是不能通用的。写的程序的指令,也是在内存中的,对应的有bug的代码,也是其中的一段指令,找到有bug的代码指令,直接修改这里的指令,修改成没有bug的版本,或者在这个指令上加入跳转指令,让有bug逻辑不去执行,而是新增加一个正确的指令.

2024-06-06 22:30:15 666

原创 JDBC知识

在编程中,写代码不是从0开始,会调用别人已经写好的代码,我们称之为"库",这些代码里就提供的一些 类/方法/函数 就可以称为API.

2024-06-01 12:19:26 869

原创 Mysql中的事务

描述了多个事务并发执行的时候,相互之间产生的影响是怎样的,MySQL是一个客户端-服务器结构的程序,一个服务器通常会给多个客户端提供服务,因此很可能,这多个客户端,就同时给这个服务器提交事务来执行.与之相对的,服务器就需要同时执行这多个事务,此时就是并发,此时如果这些事务同时执行,恰好也是针对同一个表,进行一些增删查改,此时就可能会引入一些问题{这种情况下,一个事务可以读取另一个事务未提交的数据,此时就可能产生脏读,幻读,不可重复读三种问题,但是此时,多个事务并发执行程度也是最高的,执行速度也是最快的.

2024-05-30 14:08:21 409

原创 谈谈关于mysql索引的理解

创建索引时一定要提前规划好自己的需求,对一个表中的那几列需要进行索引,可以更方便的查找,如果一个表已经创建好了,需要对有的列进行添加索引的操作,是非常危险的操作,一定要小心慎重,针对空表,数据量小的数据库进行创建索引操作,不会有太大危险,如果是数据量特别大的表,会产生大量的IO操作,直接把数据库给搞挂了.万一有一个表,没有提前创建索引,现在又有很多的数据,非加索引不可,那么我们可以重新创建一个数据库,然后将这个数据库的数据导入到新数据库中,然后切换程序访问新数据库。show index from 表名。

2024-05-28 14:51:48 563

原创 优先级队列(堆)

1.堆总是一颗完全二叉树,2.堆中某个结点的值总是不大于或不小于其父节点的值。堆分为大根堆 小根堆。

2024-04-27 14:12:32 177

原创 二叉树学习

深度优先是先遍历完一条完整的路径(从根到叶子的完整路径),才会向上层折返,再去遍历下一个路径,前序遍历就是一种深度优先遍历。5.对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有结点从0开始编号,对于序号为i的结点有。2i+1>n 无左孩子 2i+2>n无右孩子。2.若规定根节点的二叉树的深度为1,则深度为k的二叉树的最大节点数是2的k-1次方。1.若规定根节点的层数为1,则一颗非空二叉树的第i层上最多有2的i-1次方结点。节点的层次:从根开始定义,根为第一层,根的子节点为第二层依次类推。

2024-04-20 15:26:01 292

原创 数据结构基本知识的学习

考虑时间复杂度,考虑最坏的情况,剩最后一个我才找到,我需要的那个数字,每一次去掉一半,设原来有n个数,砍了x次剩余最后一个数那么可以列出,n*二分之1的x次方 = 1,可得x等于log以2为低n的对数。在Java当中,数组是一种类型在new数组的时候必须是一个具体的类型,类名后面代表占位符,表现当前是一个泛型类。因为Object是所有类的父类,但是Object[]不是所有数组的父类,是一种单独的类型。编译的时候1.每次存放数据的时候,会检查你存放的数据,是不是和你指定的类型一样。

2024-03-23 19:51:09 662

原创 学习异常知识

程序先执行try的代码,如果try中的代码有异常则会结束try中代码看和catch中的异常类型是否匹配。找到匹配类型就会结束catch中的代码,一直向上调用处理异常,指到JVM来进行处理。finally一定会被执行,不管是否抛出异常,都被执行,资源会回收。异常的处理,如果一直向上传递都没有合适的方法处理异常,那么最终就会交给jvm处理,程序就会异常终止。没有捕捉到对应的异常就会交给jvm处理,如果交给jvm处理程序就会直接终止。异常分为运行时异常(非受查)(程序开始运行的时候)和编译时异常(受查)

2024-03-17 15:18:51 282

原创 内部类学习

如果内部类和外部类存在相同的变量名如果要访问外部类的变量,就需要外部类名加.this.变量名。4.局部内部类定义在方法里面,只能在当前方法当中使用,不能被修饰符修饰。外部类和内部类的概念:定义在A类当中的类B,B为内部类,A为外部类。在Java中可以将一个类定义在另一个类或者方法的内部。创建静态内部类对象时,不需要先创建外部类对象。2.静态内部类(使用更多)被static修饰。1.实例内部类:定义在类的内部方法的外部。new 通过类.静态内部类去访问。只能访问外部类中的静态成员。没有名字没有被接受的对象。

2024-03-16 13:57:57 127 1

原创 Java接口

而object是所有类的父类所有需要向下转型,转换为Student,自定义类型想要成功必须在类的后面加上一个接口Cloneable接口。以后只要是自定义类型数据一定要重写hashcode(用来确定对象在内存中储存的位置是否相同,在哈希表中才会用到)和equals方法。核心区别:抽象类中可以包含普通方法和普通字段,这样的方法和字段可以被子类直接使用,而接口中子类必须重写所有抽象方法。克隆前提,需要对clone进行重写,因为clone是object类中的,需要使用super关键词进行重写。

2024-03-10 16:27:42 127 1

原创 抽象类和接口

1.一个方法可以被修饰为abstract,此时代表这个方法可以不进行实现。此时被称为抽象方法!,2.如果一个类当中包含抽象方法此时这个类必须是抽象类。没有抽象方法,这个类也可以称为抽象类问题:什么情况下一个类可以被定义为抽象?当不能描述具体的对象的时候3.抽象类当中定义的成员和普通类没有区别;4.抽象类不可以被实例化问题抽象类不能实例化存在的意义?为了被继承5.当一个普通类继承这个抽象类之后,必须重写抽象类的抽象方法6.抽象类也是可以发生动态绑定和向上转型的,也可以发生多态。

2024-03-07 16:44:19 248

原创 多态和继承

继承关键词extendsdog和cat类都继承了Animal子类 父类派生类 基类子类继承父类之后,必须新添加自己特有的成员,体现与基类的不同,否则没必要继承了。

2024-03-05 16:48:14 717 1

原创 类和对象1

在方法内局部变量优先使用,值赋值给了形参而没有赋值到类中的对象,所以打印出来类的对象的值是0.对于引用类型来说是null 其他的简单类型是0值。对于一个类的成员变量。只要存在任何一种构造方法,编译器都不会在提供不带参数的构造方法。创建对象由编译器自动调用,并且在对象的生命周期内只调用一次。调用当前类中其他的构造方法,调用的是带有三个参数的构造方法。如果不加this那么形参与对象相同时,对象的值就为0。首先它是一个方法:返回值 方法 参数列表(){}构造方法不一样没有返回值且方法名和类名一样的。

2024-02-28 21:23:09 112 1

原创 数组的定义与使用

数组null与数组.length的区别 null没有指向的对象 而length==0是有指向的对象只不过没有元素。栈存储的是局部变量,而堆相对于栈更大一点存储的是对象。关于main函数的参数String[] args 存储java运行是命令行参数。数组名不是基本数据类型,因为存储的是地址,所以是引用数据类型。1.java虚拟机栈 2.本地方法栈 3.堆 4.方法区 5.程序计数器。模拟实现Arrays中的toString利用字符串拼接的思想完成。2.二分查找:建立在当前你要找的数据是有序的情况下。

2024-02-27 21:52:43 143 1

原创 方法的使用

1.做到重复利用,一段代码可以在多处地方被使用。2.可以更好的理解。方法由三部分组成,返回值和方法名(必须采用小驼峰的形式)和形式参数列表一定要有返回值。这就是一个方法的调用。匹配操作:1.参数类型匹配2.参数个数匹配3.返回值类型匹配。在Java当中不需要声明方法。没有前后顺序方法的调用会在栈上开辟空间(叫做栈帧)遇到return代表方法的结束,栈帧就会回收 ,一个花括号走完也认为方法结束。

2024-02-21 20:33:38 206 1

原创 Java数据类型及运算符

浮点型:float(单精度) double(双精度) 任何小数都没有一个精确的,但是可以精确到小数后几位,浮点数与整数存储方式不同。都是byte相加为什么会报错,Java会将所有小于四个字节的变量都会提升成四个字节。然后以 表达式2(布尔表达式) 语句块 表达式3这种方式执行 ,表达式1只会被执行一次。2.右移>> 最左边补符号位,符号位是1,补1,符号位是0,补0. 右移相当于除法。执行顺序:表达式1 表达式2(布尔表达式) 语句块 表达式3。^ 按位异或 对应位上不一样的地方为1,一样的地方为0.

2024-02-03 11:17:10 455 1

原创 认识JAVA

JVM是整个Java实现跨平台的最核心的部分,所有的Java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。JDK是Java开发工具包 ,包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。JRE是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。

2024-01-31 16:44:47 150

原创 数据结构链表

之前学习了顺序表,但是顺序表每次头插或中间插入,都必须挪动数据,而且每次扩容,都会造成消耗,并且会造成空间的浪费,那么思考有没有一种数据结构能弥补上述缺点呢。为什么打印的时候编译phead,而是用一个临时变量呢,因为用phead最后走向了空指针,如果以后在想用phead就是空指针了。链表是由一个一个结点组成。结点由两部分组成:要存储的数据+指针(结构体指针)。由于每次都是要使用新的结点,所以申请结点的方法封装到一个函数中。以下是实现链表结构的头文件所包含的函数。有头插尾插也就有头删和尾删了。

2024-01-25 16:37:00 327 1

原创 通讯录实战项目

通讯录的初始化与销毁,可以调用顺序表的初始化函数,因为通讯录跟顺序表的本质是一样的,只不过存储数据不一样,直接就通讯录的形参传给顺序表的初始化函数就完成了该功能。前置声明就好比函数的声明,例如swap()函数中调用add(),而add()在swap()的后面则在swap()前面加上一句add(),就实现了函数的声明。通讯录就是变形的顺序表,原来的顺序表中存储的是一个int数据,而通讯录中的数据是一个结构体类型,做了一个数据类型替换;上面就是通讯录代码主要部分的主要逻辑部分。通讯录的增加联系人代码部分。

2024-01-22 10:08:10 481

原创 顺序表 实现增删改查功能

数据结构是计算机存储和组织数据的方式;顺序表是线性表的一种线性表在逻辑上是线性结构,也就是说连续的一条直线,但是在物理结构上不一定是连续的。线性表在物理上存储时,通常以数组和链式结构的形式存储。顺序表在逻辑上是线性结构,物理结构也是连续的。顺序表的底层结构是数组,对数组的封装,实现增删改查等接口。在数组的基础上,增加了更多的功能。静态顺序表、数组大小已知,存储数据的底层逻辑都是数组;若长度不够,则会导致后续的数据保存失败。动态顺序表,数组大小未知;typedef对结构体的使用,两种是同一方法。

2024-01-20 11:11:30 409

原创 预处理详解

#运算符 可以把位于他两边的符号合成一个符号,##被称为记号粘合,这样的连接必须产生一个合法的标识符,否则结果是未定义的;操作符优先级:宏的每个元素都必须加上括号,否则会产生难以预估的后果,而函数的只求值一次,求值结果更容易预测;带有副作用的参数:宏的变量如果使用++这种操作符参数会被多次计算,而函数的参数只在传参时求值一次。参数类型:宏的参数与类型无关,只要对参数操作合法,就可以使用任何参数,而函数的类型非常严格;#运算符将宏的一个参数转化成字符串字面量,它仅出现在带参数的宏的替换列表中。

2024-01-18 20:13:30 289 1

原创 编译和链接

将编译进行的符号汇总(每个.c文件中包含的所有符号)和汇编形成符号表(每个符号都有自己的地址,进行合并,如果在一个文件中进行外部声明,则那个符号的地址是无效的)进行符号决议和重定位,3.处理#include预编译指令,将包含的头文件的内容插入到该预编译指令的位置,这个过程是递归进行的,也就是说被包含的头文件可能包含其他文件。.c为后缀的文件经过预编译生成为.i的后缀文件——————>编译生成后缀为.s的文件————>目标文件为临时文件,不同的操作系统中目标文件的后缀不同,在Linux中目标文件后缀为.o。

2024-01-17 12:36:51 350

原创 关于C语言的函数栈帧的创建和销毁

由于使用编译器为vs2013,该电脑未配备,无代码演示1.寄存器:eax,ebx,ecx,edx ebp,espebp,esp这2个寄存器中存放的是地址,这两个地址是用来函数栈帧的每一个函数调用都要在栈上开辟空间,开辟的空间被称为函数栈帧,由ebp(栈低指针),esp(栈顶指针)维护栈区的使用习惯是先使用高地址在使用低地址,在VS2013中main函数的调用逻辑,3.main压栈(push):在顶上指针放进去一个元素;出栈(pop):从顶上指针拿走一个元素;

2024-01-04 17:30:46 407 1

原创 关于文件操作

一般情况下我们想向流写入数据,或者从流中读取数据,就必须打开流,然后操作。标准流当c语言程序启动时,默认打开三个流;1.stdin-标准输入流,从键盘输入,scanf函数就是从标准输入流中读取数据2.stdout-标准输出流,输出至显示器界面,printf函数将信息输入到标准输出流3.srderr-标准错误流,输出到显示器界面;stdin,stdout,srderr这三个流的类型是文件指针:FILE*,通常称为文件指针;C语言中就是通过FILE*的文件指针来维护流的各种操作的;文件指针。

2024-01-03 12:47:12 907 1

原创 关于c语言中动态内存管理知识点

在这种情况下,realloc会在内存的堆区从新找一块空间(满足新的大小空间的需求),同时会把旧的数据拷贝到新空间,然后释放旧的空间,同时 返回新的空间的起始地址;malloc/calloc/realloc 申请的空间 如果不主动释放,出了作用域不会销毁的,释放的方式:1.主动释放,2.直到程序结束,才由操作系统回收;2.情况2,在已经开辟好的空间的后面,有足够的空间直接扩大,扩大空间后,直接返回旧的空间的起始地址;1.该函数向内存申请一块连续可用的空间,并返回指向这空间的指针;4.申请的空间在内存的堆区;

2023-12-30 11:32:58 344 1

原创 自定义类型的学习

但是编译器只为最大的成员分配足够的内存空间,联合体的特点是成员公用同一块内存空间,也叫共用体;4.如果嵌套结构体,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小,就是所有最大对齐数的整数倍;为什么会存在内存对齐:1.平台原因:不是所有的平台都能访问任意地址的任意数据,某些硬件平台只能在某些地址处取某些特定类型数据;3.结构体的总大小为最大对齐数(结构的每个成员都有一个对齐数,所有对齐数中最大的)的整数倍;2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;

2023-12-28 16:39:20 330 1

空空如也

空空如也

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

TA关注的人

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