自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 重写equals一定要重写hashcode吗?

重写equals一定要重写hashcode吗?

2022-01-02 13:07:15 654

原创 Java垃圾回收机制(GC)

如何识别出当前对象是否是垃圾垃圾:也就是这个对象以后没人使用(对于这个代码起不到贡献了)引用计数(在Java中实际上没用到)就比如有一个对象,创建对象的同时,给这个对象搭配一个计数器;每次有一个引用指向这个对象,计数器就 +1,每次有一个引用被销毁那么计数器就 -1 ;当计数器为0的时候,这个对象也就没人引用了,自然也就成了垃圾;举个例子:class Test{ void test(){ Test t = new Test(); Test t2 = t; }}在上述代码中,当执行

2021-08-20 17:13:07 546 8

原创 多线程环境下使用哈希表

HashTable单纯的使用一个synchronized进行加锁~,具体相当于针对整个 HashTable对象,但是坏处就是这样的话锁冲突的概率是非常高的如果有多个线程,线程1操作的在第一个链表上,线程2操作的元素在别的链表上,这个时候不涉及到线程安全。此时两个线程,修改不同的变量,实际上是没有线程安全的,但是HashTable直接一把锁,锁住了,线程1去操作的时候,线程2就会被阻塞等待,这样效率就会比较低。此外,在扩容的时候,如果某个线程T正好触发了扩容,那么这个T就倒霉了,就要负责完成整个扩

2021-08-17 18:11:43 1031 1

原创 Java中synchronized的工作原理

“锁膨胀” 的过程~场景:多个线程尝试i++,假设这些线程不是同时运行的。1)第一个线程开始i++,就需要先加锁~但是第一个线程首次加锁,不是进行真加锁,而只是在对象头里通过一个特殊标志位,标记一下(某个线程想要获取到锁),这里由于是一个线程进行操作,所以还不涉及到线程问题,所以只是标记一下。这个线程赌后面没有其他线程来竞争这个锁!!这也是一个乐观锁。同时这不是一个真的加锁,而只是标记了一下,所以我们也叫作偏向锁。2)当第一个线程以偏向锁的状态进行i++的过程中,第二个线程也来尝试竞争锁~~这个

2021-08-17 15:08:11 192

原创 Java中的一些锁的概念和CAS,以及ABA问题

所谓策略,也就是解决一件事有不同的方法!举个例子:问男生追女生的方式有哪些?就好比你可以直接下手,去要她的联系方式;也可以通过她身边的闺蜜下手,一步一步的靠近她;也或者先去和她搞好关系后,再去表白等等。乐观锁和悲观锁乐观锁: 假设认为数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。(认为冲突的概率不是很高,做的工作会更少一些,付出的成本也更低~)CAS(Compare A

2021-08-16 02:37:21 234

原创 Java中的定时器Timer

简单来说,定时器就相当于一个“闹钟”,给定时器设定一个任务,约定这个任务在xxx时间之后执行~Timer类提供了一个核心接口,schedule(安排) 指定一个任务交给定时器,在一定时间之后再去执行这个任务~如何实现定时器的效果~Timer中要包含一个Task类,每个Task就表示一个具体的任务实例,Task里面包含一个时间戳(啥时候执行这个任务),还包含一个Runnable实例(用来表示任务具体是啥)。Timer里面通过一个带优先级的阻塞队列,来组织如干个task。这里的优先级是按照时间的先后

2021-08-13 22:24:47 573 2

原创 Java多线程中的阻塞队列

概述阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景。生产者消费者模型生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡

2021-08-13 20:24:50 359

原创 Java中的单例模式

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。1、单例类只能有一个实例。  2、单例类必须自己创建自己的唯一实例。  3、单例类必须给所有其他对象提供这一实例。饿汉式单例//实例的创建出现在‘类加载’阶段class SingleTon{ //创建一个成员,用来保存唯一的一个SingleTon 实例 private static SingleTon inatance = new SingleTon(); //提供一个今天的静态的方法,来获取到当前实例

2021-08-12 20:27:53 110

原创 Java多线程之对象等待集

对象等待集起到的效果就是,协调多个线程之间执行的先后顺序~举个例子:一群人去ATM取款机里去取款,第一个是张三进去去钱,张三进去后,取完钱出来,发现钱取的不够,于是又进去再取一次,这次再出来的时候,又发现钱取多了,再次进去存一点,这样反反复复,就会导致后面排队的人一直用不到取款机。由于多线程直接是“抢占式”执行,所以往往某一个线程反复的执行,就会导致后面排队的线程,迟迟没有机会去CPU上执行,就会导致线程饿死~为了解决这个问题,我们借助对象等待集,合理的协调多个线程之间执行的先后顺序~wait()

2021-08-12 16:50:39 191

原创 Java中volatile的用法

volatile起到的效果是辅助保证线程安全,volatile能够禁止指令重排序,保证内存可见性,但是不保证原子性。主要用于读写同一个变量。观察如下代码:public class TestVolatile { static class Counter{ public int flag = 0; public int x = 0; } public static void main(String[] args) { Counter

2021-08-11 23:19:21 1806

原创 Java中的synchronized用法

synchronized是Java里的一个关键字,起到的一个效果是“监视器锁”~~,它的功能就是保证操作的原子性,同时禁止指令重排序和保证内存的可见性!public class TestDemo { static class Counter{ public int count = 0; public void add(){ count++; } } public static void main(Str

2021-08-11 01:56:21 467 2

原创 Java多线程安全问题(原子性,内存可见性,指令重排序)

概述多线程虽然是更轻量的(相比于多进程来说)来完成了并发编程。但是多个线程是访问同一份内存资源的。并且线程是一个“抢占式”执行的过程(这些线程谁先执行,谁后执行,完全取决于系统的调度器),由于这里的不确定性太多,就可能会导致多个线程在访问同一个资源的时候,出现bug~“线程安全问题”。举个例子:在一个桌子上放着一盘鸡肉,张三和李四老铁,同时看上了一个鸡大腿,两个人都要去抢这个鸡大腿,这个时候,两人就可能会打起来。就好比线程1和线程2同时争夺一个资源,就会发生线程不安全问题。那么这里的“访问” 是啥意

2021-08-10 21:23:35 904

原创 Java多线程中常用方法

run()方法(只是一个内部方法)run()方法只是一个类中的普通方法,调用run方法跟调用普通方法一样。方法 run()称为线程体,它包含了要执行的这个线程的内容,线程就进入了 【运行状态】,开始运行 run 函数当中的代码。Run 方法运行结束, 此线程终止。再调用start方法报错的。然后 CPU 再调度其它线。启动线程start()方法(开启一个线程)在 Java中启动多线程调用的是start方法。在start方法中,真正实现多线程的是一个本地的方法start0。调用start方法

2021-08-10 17:21:26 508

原创 K组翻转链表

力扣链接题目描述:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。大题思路如下:翻转局部链表,也就是简单的翻转链表1.定一个傀儡节点temp,让pre 和 cur执行傀儡节点;2.让cur先走k步,然后让start指向per.next,end指向cur,cur指向cur.next;3.翻转局部后,在重新拼接class Solution { pu

2021-08-09 19:56:58 122

原创 Java多线程的常见属性(线程状态,守护线程)

常见的属性属性获取方法IDgetId()名称getName()状态getState()优先级getPriority()是否为守护线程isDaemon()是否存活isAlive()是否被中断isInterrupted()ID 是线程的唯一标识,不同线程不会重复通过getName()来获取到当前线程的名称public class TestDemo { static Thread t1 = new Thread(){

2021-08-09 19:23:12 204

原创 Java实现LRU缓存机制

力扣链接方法一:使用 LinkedHashMappublic class LRUCache{ int capacity; Map<Integer, Integer> map; public LRUCache(int capacity) { this.capacity = capacity; map = new LinkedHashMap<>(); } public int get(int key) {

2021-08-09 13:45:12 286

原创 Java多线程(创建线程的方法)

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。创建多线程通过继承 Thread 类,重写run方法该方法的好处是 this 代表的就是当前线程,不需要通过Thread.currentThread() 来获取当前线程的引用。public class TestDemo extends Thread{ @Override public void run() { System.out.println("创建

2021-08-09 00:51:31 118

原创 进程和线程

冯诺依曼体系结构首先我们需要先了解一下冯诺依曼体系结构:我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。计算机大部分都是由一个一个硬件组成的输入单元:包括键盘,鼠标,扫描仪,写板等。中央处理器(CPU):含有运算器和控制器等。输出单元:显示器,打印机等同时这里也需要注意:这里的存储器指的是内存。不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)。外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中

2021-08-08 19:04:20 123

原创 复杂链表的复制

力扣链接牛客链接复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。此题,我们需要用到链表和哈希表的用法如下图:1.定义一个cur指向head,遍历链表,每次遍历的时候new一个node节点把当前的节点的值赋给node,但是next域不能赋值,因为如果你要复制一个链表,那么复制出来的链表都会有新的地址,如果你把原来节点的next域,也复制给新的node,就不是深拷贝了,2.那么我们要怎么解决呢?我

2021-08-07 16:00:11 116

原创 Java删除链表中重复的结点

牛客链接1.由于链表是排序好的,所以就减少了一些麻烦首先我们需要定义一个傀儡节点(head),来减少边界判断,把后续的答案往后的答案接在傀儡节点之后;让傀儡节点连接,整个链表同时,定义一个cur 指向 傀儡节点的下一个节点定义一个pre指向当前傀儡节点此时需要判断当前cur节点是否和他的下一个节点重复,如果不重复,pre指向cur,cur指向cur.next;注意:判断cur下一个节点的值时,需要先判断cur.next是否为空,不然会导致空指针~~此时cur的值和cur.next的值相

2021-08-07 13:24:01 248

原创 Java异常分类及处理

概念        如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。异常分类Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 Error 和 ExceptionError  &nbsp

2021-08-06 22:54:55 104

原创 按之字形顺序打印二叉树

牛客链接思路:总体来说,思路和二叉树的层序遍历一样只不过通过,队列和栈来解决,在遍历的时候,奇数层入队,而偶数层入栈队列是先入先出,栈是先入后出,所以可以很好的满足之字打印然后遍历队或栈的元素,放在list里面过程很简单,在遍历的时候,奇数层入队,而偶数层入栈,取出栈或队列的元素放入list中就OK了import java.util.*;public class Solution { public ArrayList<ArrayList<Integer> &g

2021-08-06 13:25:49 91

原创 二叉树的层序遍历(从上到下打印二叉树)

牛客链接思路:1 .初始化:一个队列Queue< TreeNode > queue, 将root节点入队列queue第一次size = 1,2. 如果队列不空,做如下操作:注意每次进入循环时,先获取到队列里元素的个数,即queue.size();第,二次进去时,size为2,弹出队列头,保存为,将cur的左右非空孩子加入队列循环2,3步骤,直到队列为空public class Solution { public ArrayList<Integer&gt

2021-08-05 22:19:40 164

原创 以太网(报头格式 | MTU | ARP)

以太网“以太网” 不是一种具体的网络, 而是一种技术标准; 既包含了数据链路层的内容, 也包含了一些物理层的内容. 例如: 规定了网络拓扑结构, 访问控制方式, 传输速率等;例如以太网中的网线必须使用双绞线; 传输速率有10M, 100M, 1000M等;以太网是当前应用最广泛的局域网技术; 和以太网并列的还有令牌环网, 无线LAN等;以太网帧格式源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;帧协议类型字段有三种值,分别对应IP、ARP、RA

2021-08-05 20:07:05 2789

原创 IP协议(路由选择 | 路由表生成算法)

路由选择简单来说:就是在复杂的网络结构中, 找出一条通往终点的路线;举个例子:张三去了国外,假如说他要去国外的银行取点钱,但是他不知道再哪,他就一个人一个人的问路,最后找到了目的地。这一次一次询问的过程就是"路由"。每个路由器内部都会维护一个数据结构“路由表”,这个路由表里就包含了当前路由器的一些相邻设备的相关情况。现在客户端想访问服务器1.2.3.4,那么客户端构造一个IP数据报1).先把这个数据报发给路由器1,问一问路由器是否知道这个IP地址,在哪?根据这个IP查询路由表;如果路由器

2021-08-05 17:33:47 817

原创 IP协议(IP地址的数量限制 | NAT机制)

IP地址的数量限制我们知道, IP地址(IPv4)是一个4字节32位的正整数. 那么一共只有 2的32次方 个IP地址, 大概是43亿左右.而TCP/IP协议规定, 每个主机都需要有一个IP地址.实际上, 由于一些特殊的IP地址的存在, 数量远不足43亿; 另外IP地址并非是按照主机台数来配置的, 而是每一个网卡都需要配置一个或多个IP地址。初衷:是让每个网络上的设备都有一个唯一的IP~但是现状就是IPv4地址是非常紧缺的,不够用虽然CIDR在一定程度上缓解了IP地址不够用的问题(提高了利用率

2021-08-05 15:54:52 1937

原创 栈的压入弹出序列(Java)

牛客链接输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)举例:输入:[1,2,3,4,5],[4,3,5,1,2]返回值:false首先我们要知道栈是先入后出的原理。思路:首先我们遍历pushA数组,将它依次入栈,入栈的同时判断栈头元素是

2021-08-05 14:16:23 149

原创 IP协议(报头格式 | 网段划分)

IP协议报头格式版本        占 4 位,表示 IP 协议的版本。通信双方使用的 IP 协议版本必须一致。目前广泛使用的IP协议版本号为 4,即 IPv4。首部长度        IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节。当 IP 分组

2021-08-03 19:20:17 2216

原创 TCP协议(TCP异常情况 | TCP协议总结)

TCP异常情况1.进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别        进程的结束,也会导致四次挥手的进行~~2.机器重启: 和进程终止的情况相同.(按照正确的流程重启)        此时系统就会先杀死进程,也就会触发四次挥手~~但是随着进程的杀死,系统也就会关闭,此时四次挥手就可能出现还没挥

2021-08-03 16:04:10 679

原创 Java 里的HashSet和TreeSet

SetSet与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key。Set官方文档纯 key 模型,比如:有一个英文词典,快速查找一个单词是否在词典中快速查找某个名字在不在通讯录中方法解释boolean add(E e)添加元素,但重复元素不会被添加成功void clear()清空集合boolean contains(Object o)判断 o 是否在集合中Iterator iterator()返回迭代器

2021-08-03 14:39:24 355

原创 TCP协议(延迟应答 | 捎带应答 | 面向字节流(粘包问题))

延迟应答延迟应答,也是一个提高效率的机制,也和滑动窗口密切相关~~举个例子: 张三去送货张三第一天早上送了10箱啤酒, 老板说仓库还空90箱第二天早上,再送90箱…但是现在 不这样了第一天早上,张三先送去10箱, 老板说,你先回去,晚上我在给你打电话,告诉你要多少箱, 然后晚上老板说我要100箱~(本来仓库空90箱,但是老板又多买了10箱)此时老板给我的应答更迟了,也就留给了超市一定时间去卖啤酒,所以老板告诉张三的结果会更大一些;但是一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就

2021-08-02 23:04:22 420

原创 TCP协议(滑动窗口 | 流量控制 | 拥塞控制)

滑动窗口在上一篇博客里确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段. 这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候.举个例子张三早上要去买早餐,他要吃一笼包子,两个烤面筋,还有一杯奶茶那么他怎么买呢??1)他先买包子,等包子弄好了,再去买面筋,面筋弄好了,再去买奶茶这就相当于一发一收2)他点完包子,立马转身去点面筋,然后再去点奶茶这样我们三份数据的时间就合并在一起了,那么最终等多久,就看那个东西做好最慢,时间

2021-08-02 19:00:05 378

原创 Java中的HashMap和TreeMap

1 概念及场景        **Map是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。以前常见的搜索方式有:1). 直接遍历,时间复杂度为O(N),元素如果比较多效率会非常慢2). 二分查找,时间复杂度为O(log2 N) ,但搜索前必须要求序列是有序的        上述排序比较适合静态类型的查找,即一般不

2021-08-02 14:07:45 582

原创 Java 用队列实现栈 | 用栈实现队列

力扣链接首先我们要了解栈和队列的机制栈和队列解题思路:首先我们知道,队列是先进先出,栈是后进先出。然后我们用两个队列来解决。一个队列为主队列,一个为辅助队列,当入栈操作时,我们先将主队列内容导入辅助队列,然后将入栈元素放入主队列队头位置,再将辅助队列内容,依次添加进主队列即可。class MyStack { public Queue<Integer> q1; public Queue<Integer> q2; /** Initialize you

2021-08-02 01:15:27 199

原创 Java栈和队列

栈概念一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。压栈: 栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。入栈:栈的删除操作叫做出栈。出数据在栈顶。首先栈中的数据元素准循着先进后出(后进先出)的原则!!!举个例子:就和我们现实生活中用口袋装东西一样,往里面放东西,往往先放的物品会在最下面,最后放的东西会在最上面,那么取东西时,也是一样最后放

2021-08-02 00:54:38 139

原创 TCP协议连接管理(三次握手/四次挥手)

三次握手建立连接三次握手的本质,其实就是确定通信双方,发送能力和接受能力是否正都正常举个例子:张三有约李四出去通宵(但是实际是的三次握手比我这个例子更复杂)        所以三次握手的核心目的就是为了测试一下双发的发送和接受能力是否正常,如果任意一方的发送或者接受出现问题,那么后续的传输就进行不了了,所以我们通过三次握手至少先保证了整体的通信基本正常。这个环节也就奠定了可靠性的基础。后面在传输时才涉及到确认应答机制和

2021-08-01 21:41:52 224

原创 TCP协议图解(确认应答机制, 超时重传机制)

TCP协议格式标红的位置        1.序号:Seq序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。        2.确认序号:Ack确认号占32位,客户端和服务器端都可以发送,Ack = Seq + 1。       &

2021-07-31 22:17:41 1838

原创 环形链表问题

力扣链接牛客链接给定一个链表,判断链表中是否有环。如果链表中存在环,则返回 true 。 否则,返回 false 。方法1:快慢指针时间复杂度o(n),空间复杂度O(1)定义两个指针,一个指向头结点的慢指针(slow),一个为头结点下一个节点的快指针(fast)循环判断条件由于fast一次走两步,所以fast!=null 并且 fast.next != null && slow!=null 预防循环时空指针异常进入循环,fast走两步,slow走一步,如果fast ==

2021-07-31 13:54:30 154

原创 数据包的封装和分用

系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:第一章 Python 机器学习入门之pandas的使用提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例

2021-07-30 23:42:26 515

原创 移除链表元素

力扣链接给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。方法一:双指针思路:第一步:定义两个指针,一个指向头结点(prev),一个指向头结点的下一个节点(cur)第二步:遍历链表,如果该节点的值等于要删除的值,让prev的next域存放cur的next域如果cur的值不等于要删除的值 两个指针都往后走一步 prev指向curcur继续向下走,当cur为空时退出循环第三步:判断头结点是否为要

2021-07-30 12:02:49 112

空空如也

空空如也

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

TA关注的人

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