- 博客(40)
- 收藏
- 关注
原创 多线程代码案例 - 1
目录单例模式1. 饿汉模式2. 懒汉模式单例模式与多线程问题1问题2问题3完!单例模式是一种设计模式。单例 ==》 即单个实例(对象),某个类,在一个进程中,只应该创建出一个实例(是原则上不应该有多个),使用单例模式,可以对我们的代码进行一个更为严格的校验和检查。实现单例模式的方式有很多种,这里介绍最基础的两种实现方式:1. 饿汉模式 2. 懒汉模式我们创建一个类,名为 Singleton 希望这个类在一个进程中,只能有唯一的实例这个引用,就是我们期望创建出的唯一的实例的引用:在这行代码中,使用 stati
2025-04-02 21:29:52
1017
6
原创 多线程 - wait notify
线程安全 --> 死锁,是在进行多线程的时候,比较常见的问题,也是比较严重的问题!!!1. 一个线程,一把锁。这个线程连续对这个锁加锁两次,如果这个锁不是可重入锁,就容易发生死锁现象。2. 两个线程,两把锁。线程 1 获取锁 A,线程 2 获取锁 B,之后,两个线程在不解开本来获取的锁的前提下,再彼此尝试获取对方的锁,就会发生死锁现象。3. N 个线程 M 把锁。哲学家就餐问题中是 N 个线程 N 把锁,如果是 N 个线程 M 把锁,场景变换一下,也会可能构造出死锁的。。
2025-04-01 19:07:57
663
4
原创 多线程 - 线程安全 3
此时 JVM 就可能会做出代码优化操作,即把上述 load 操作给优化掉(只有前几次进行 load,后续发现,反正 load 的结果都一样,静态分析代码,也没看到后续操作哪里对 fg 进行了修改,因此直接就激进的把 load 操作给干掉了),干掉 load 操作后,就相当于,不再重复读取内存了,直接使用寄存器之前”缓存“的值了,从而大幅度的提高了循环的执行速度。我们更希望的是,让我们的代码,100%不出现问题,即无论当前这个线程代码是怎么写的,不论有没有 sleep,都不要出现这种内存可见性问题。
2025-03-31 19:22:01
746
4
原创 多线程 - 线程安全 2 -- > 死锁问题
1. 【根本原因】 线程的随机调度,抢占式实行(罪魁祸首,万恶之源),多个线程执行的顺序,存在诸多变数,我们要做的就是需要保证任何一种变数下,执行结果都是正确的,无 bug 的。2. 多个线程同时修改同一个变量。3. 修改操作不是原子的。count++ 本质上是 3 个指令,load,add,save...类似的 +=,-= 也是非原子的,但是 = 这种操作,一般是原子的。4. 内存可见性5. 指令重排序。
2025-03-30 22:16:00
857
原创 多线程 - 线程安全
如下代码,让 count 在两个线程中分别自增 5000次我们预期结果应该是 100000 ,但打印的结果却和我们的预期不相同,,并且我们每次运行程序,结果都不相同,这就出现了 bug。
2025-03-30 17:36:01
1010
原创 多线程 - 线程安全引入
写一个代码,让主线程创建一个新的线程,由新的线程负责完成一系列的运算(比如:1 + 2 + 3 +... + 1000),再由主线程负责获取到最终结果。但打印结果为 result = 0,略微思考,明白了要让 t 线程先执行完,然后再打印 result。补充,其实如果主线程直接就打印 result,此时得到的结果是啥,其实是无法预期的,由于线程之间的执行顺序不确定,主线程打印的 result 可能是还没有开始计算的初始值0,也可能是过程时候的中间结果,也可能是 t 线程计算完成之后的最终结果。
2025-03-29 17:19:08
508
1
原创 多线程 --- 进程和线程的基本知识
前面我们提到了一个概念是,多任务操作系统,即希望该系统能够同时运行多个程序。本质上说,进程,就算用来解决”并发编程“这样的问题的。在一些特定的情况下,进程的表现,其实并不能很好的解决”并发编程“,比如,,此时再使用多进程编程,就会造成较大的。早期编写服务器程序的时候,是使用C语言来进行编写的(基于一种CGI技术,该技术是一种基于多进程的编程模式)。服务器同一时刻就会收到很多请求,针对每个请求,都会创造出一个进程,给这个请求提供一定的服务,返回对应的相应。一旦这个请求处理完之后,这个进程就要被销毁了。
2025-03-24 21:26:14
955
2
原创 计算机是如何工作的
CPU,是计算机系统的核心部件,负责执行计算机的基本算数,逻辑,控制和输入输出操作指令。是计算机的运算和控制核心,是信息处理,程序运行的最终执行单元。CPU的制作工艺非常精密,现今较为出名的公司:(1)英特尔(2)AMD(3)高通。
2025-03-23 18:35:08
748
2
原创 java_Lambda表达式
Lambda表达式的优点很明显,在代码层次上来说,使得代码变的非常整洁。缺点也很明显,代码易读性差。1.代码简洁,开发迅速2.方便函数式编程3.非常容易进行并行计算1.代码可读性变差2.在非并行计算中,很多计算未必有传统的for性能高3..不容易进行调试。
2025-03-10 08:45:10
789
5
原创 java_枚举的使用
1.枚举本身就算一个类,其构造方法默认就算私有的,且都是默认继承于java.lang.Enum2.枚举可以避免反射和序列化的问题。
2025-03-09 18:42:45
1283
4
原创 java_了解反射机制
Java的反射(reflection) 机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到对应的属性和方法,就可以对部分类型信息进行修改。这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射(reflection)机制。
2025-03-09 17:28:02
1019
1
原创 java数据结构_再谈String_10
"池" 是编程中的一种常见的, 重要的提升效率的方式, 我们会在未来的学习中遇到各种 "内存池", "线程池", "数 据库连接池" .... 比如:家里给大家打生活费的方式 1. 家里经济拮据,每月定时打生活费,有时可能会晚,最差情况下可能需要向家里张口要,速度慢 2. 家里有矿,一次性打一年的生活费放到银行卡中,自己随用随取,速度非常快 方式2,就是池化技术的一种示例,钱放在卡上,随用随取,效率非常高。执行String s2 = "abc"的时候,过程如下,将 a b c放入常量池中。
2025-03-05 20:47:51
1292
4
原创 java数据结构_Map和Set_HashMap 底层源码解读_9.5
resize方法较为复杂,先理解为扩容即可,如果未传入数组长度,则在resize方法中默认初始化长度为16。
2025-03-05 18:36:52
394
1
原创 java数据结构_Map和Set_面试题_9.4
但还是没办法,再研究,为什么会解答错误,预期结果是先输出 i ,再输出 love,我们的输出为先输出了love,后输出了 i,不对呀,我们明明记得在调整优先级队列的时候,考虑到了两个单词出现次数情况相同,然后让字母顺序小的单词入列,为什么此处出现了问题呢?蓦然回首,bug却在灯火阑珊处。我们在遍历map向优先级队列填入元素的时候,在minHeap.size() < k的时候,即建立前k个元素的小根堆的时候,频率相同的情况,并没有处理,我们只是在后面放满元素的时候,才处理了频率相同的情况。
2025-03-04 21:36:38
771
3
原创 java数据结构_Map和Set(一文理解哈希表)_9.3
因此在查找一个元素的时候,。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN),取决于搜索过程中。理想的搜索方法:可以。如果构造一种存储结构,通过某种函数,使得,那么在查找的时候通过该函数就可以很快找到该元素。向该结构中:插入元素:根据插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放搜索元素:对元素的关键码进行同样的计算,把求得的函数值当作元素的存储位置,在结构中按此位置取元素进行比较,若关键码相同,则搜索成功该方法称为。
2025-03-03 22:35:31
872
5
原创 java数据结构_Map和Set_9.2
Set和Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key。
2025-03-02 15:51:43
285
1
原创 Java数据结构_一篇文章了解常用排序_8.1
统计相同元素出现的次数根据统计的结果将序列回收到原来的序列中举例如下图:技术排序要先申请一个计数数组然后对序列段进行遍历,把对应出现的数据 出现的次数 再计数数组当中进行记录然后 i 向后走,重复上面的操作最终计数数组的状态为:然后遍历计数数组,如果在计数数组中值为0 说明未出现数据 重新写回数据即索引为1的值为2,说明有需要排序的序列段中有两个1,最终结果为:1 1 2 2 3 3 4 4 4 6 7 7 8 9那如何实现呢?
2025-02-26 17:52:15
1010
6
原创 Java数据结构_一篇文章搞定java对象的比较_7
上篇文章研究了优先级队列,优先级队列在插入元素中,要求插入的元素不能是null或者元素之间必须要能够进行比较,为了简单起见,上篇文章只是插入了Integer类型,那优先级队列中是否能插入自定义类型的对象呢?有如下代码:运行结果为:原因在上篇文中也有所提及,优先级队列底层使用堆,而向堆中插入元素中,为了满足堆的性质(offer方法中会检测是否有比较器,如果没有比较器会强转为Compareable),必须要进行元素的比较,而此时自定义类型Card是没有办法直接进行比较的,所以会抛出上面的异常。Java中,
2025-02-22 15:31:25
1133
11
原创 java数据结构_优先级队列(堆)_6.2
在IDEA中的PriorityQueue的Structure中可以看到PriorityQueue有多种构造方法下面为相关源码实现,此处仅作列举,后面会讲解总结:使用:默认情况下,PriorityQueue队列是小根堆,如果需要是大根堆,需要用户提供比较器:此处先不作介绍,铺垫一下。
2025-02-19 22:57:37
1010
6
原创 java数据结构_优先级队列(堆)_6.1
队列是一种先进先出(FIFO)的数据结构,但某些情况下,,那这种情况,再用普通的队列结构,就不合适了。在这种情况下:数据结构应该提供两个最基本的操作,,这种数据结构就是。
2025-02-19 18:32:31
1065
3
原创 java数据结构_二叉树的相关面试题_5.6
首先要理解题意:相同指的是两棵树的 结构 和 数值 均是相同的。如下图:p 和 q两棵树 结构和其每个结点的数值均相同,才是两棵相同的树如下图:q这棵树的结构,与p对比来讲,少了根为1的左结点,则不是两棵相同的树如下图:q的根结点的值与p不同,则不是两棵相同的树总结下来:不相同有两种情况:1.一棵树的某棵子树为空,另一棵树的对应的那棵子树不为空,如下图:2.虽然两棵树都不为空,但其值不相同注意代码的顺序一定要检查是否为空,然后再对于检查p.val和q.val是否相同。
2025-02-17 20:45:10
1078
2
原创 java数据结构_二叉树_5.5
思路:遍历思路,在前面文章中,前序 中序 后序遍历的时候,会把树中的所有结点遍历一次。可以添加一个计数器,遍历一个结点就加一次。在IDEA中测试符合预期,但还是思考,上面的方法,也没有利用到这个方法的返回值。+ 1。该代码仍是化大树为小树,逐个解决子问题过程。下图为部分递归过程,注意先递出去,再归回来。
2025-02-17 20:44:47
304
2
原创 java数据结构_二叉树_5.4
以下图为例,研究二叉树的前 中 后 序的遍历方式要重点理解二叉树的递归过程,不断的将大树分解为小树,,如下图,以A为根结点的时候,红色框中的是其左子树和右子树,在A的左子树中,又可以以B为根,来分解出一棵新的树(绿色框中),其中,以B为根结点,D为左子树,E为其右子树...以这个思路,可以将一棵大的二叉树逐渐分解为小的二叉树。接下来实现用递归的方法来实现前 中 后序的遍历。
2025-02-09 19:19:23
1121
5
原创 java数据结构_二叉树_5.2
一棵二叉树是结点的一个有限结合,该集合:1.为空2.是由加上两颗别称为的二叉树组成。如下图:从上图可以看出:1.二叉树是不存在度大于2的结点,也就是说二叉树中的结点的度 <= 22.二叉树的子树是有左右之分的,次序不能颠倒,因此二叉树是有序树。(此处的有序并不是大小有顺序,是逻辑上的左右有序)补充:对于任意二叉树都是由一下的几种情况复合而成的,也就是说,二叉树中只会出现下图中的几种情况。
2025-02-05 23:40:27
611
3
原创 java数据结构_二叉树_5.1
从根开始定义,根为第 1 层,根的字结点为第 2 层,以此类推。:若一个结点含有子结点,则这个结点称为其字结点的父结点。如上图A是B的父结点,A也是C D E...的父结点, E是I的父结点...如上图,所有结点中,度最大的是A的度为6,所有上图的树的度为6。如上图,A没有双亲结点,A为根结点,一棵树中,只有一个根结点。:一个结点含有的子树的根节点称为该结点的子结点。如图,E为A的子结点,I为E的子结点...:度为0的结点称为叶结点。如图2,E结点即有B为父结点,又有C为父结点,则图2不是树型结构。
2025-02-05 16:47:23
716
2
原创 java数据结构_栈、队列的两道面试题_4.3
首先分析,因为栈和队列的原则不一样,栈是后进先出,队列是先进先出,肯定是无法仅仅使用一个队列来实现栈。可以用两个队列来模拟实现1. 两个队列qu1 qu2同时为空的时候,代表模拟实现的栈也是空的2. “出栈”的时候 出不为空的队列,出 size -1 个元素,出完size - 1个元素之后,剩下的最后的一个元素,就是模拟实现的栈出栈的元素3. "入栈“的时候 入到不为空的队列中。
2025-02-04 23:11:27
551
2
原创 java数据结构_栈和队列_4.2
4..1中,栈都是底层使用数组实现的,其入栈和出栈的时间复杂度都是O(1)。那如果要用链表实现栈,该怎么实现?使用:时间复杂度(要遍历链表):相当于删除链表最后的尾巴节点,时间复杂度仍为,也要遍历整个链表使用:时间复杂度:因为栈后进先出的特性,出栈就相当于删除头节点,所以时间复杂度也为但也在前面提到过,可以给单链表的尾节点添加一个last此时使用:时间复杂度为因为有了last标记,不需要遍历了。
2025-02-04 17:35:19
880
2
原创 java数据结构_栈和队列_4.1
有四种情况:一:不匹配二:左括号不匹配三:右括号不匹配四:解决问题:首先要遍历提供的字符串Stringi++)将括号一个一个提出来因为在往栈中存放时,要将第一个右括号与最后一个左括号匹配,所以,要判断右与左//如果是左括号,就直接入栈} else {//是右括号,就要判断这个右括号与最后一个左括号是否匹配//注意:在前面没有左括号,又因为题目要求 左括号必须与右括号闭合,所以这种情况直接返回false//此时这个top就是最后一个左括号。
2025-02-02 01:03:53
642
1
原创 java数据结构_LinkedList与链表_3.2
双向不带头非循环的链表,对比于单向,就是每个节点增加了一个prev域来存放节点的前驱则整个链表的模拟效果图如下,节点可以直接找到其前驱和后继节点对照单向链表,代码块如下:在双向链表中,增加一个last成员变量,方便了尾插法注意:并不是有了last成员变量之后, 链表才是双向,单向和双向最主要的区别是,。
2025-01-30 03:53:19
1142
3
原创 java数据结构_LinkedList与链表_3.1
则有了如下代码块调试代码,发现的确在head.next 等于 null 停止循环此时要考虑一个问题,把所有的值打印完之后,是会将head置为null的,也就是说,我们找不到head的位置了,无法继续再对链表进行操作了,这是十分后悔的结果,如何解决呢?也不难,我们创建一个其他遍历,cur,把head的值赋给cur,然后用cur循环即可。就有了如下代码,这样,变脸完成之后,head依然是指向最开始的val = 12的位置。
2025-01-29 18:52:43
757
1
原创 在 IntelliJ IDEA 中设置 “Highlight All Problems”
刚刚在敲代码的时候,注释中的中文不知道为什么IDEA也会报错。或者,在代码的右上角,将鼠标移到OFF处,也会跳出。然后会跳出,选择All Problems就好了。
2025-01-29 18:36:36
186
2
原创 java数据结构_ArrayList与顺序表_2
如果使用IDE集成开发环境,可以连续按两次shift键在点击进去之后,尽可以看到java已经为我们实现的ArrayList在集合框架中,ArrayList是一个普通的类,实现了List等等接口,上图也可以看到ArrayList继承了AbstraList,实现了等等接口,具体的框架图如下图。这里对ArrayList有六点说明。
2025-01-13 18:01:33
671
9
原创 java数据结构_1
1.多画图2.多思考3.多写代码Java集合框架(Java Collection Framework),又被称为容器(container),是定义在java.util包下的一组接口interfaces和其实现类classes。将多个元素放在一个单元中,对这些元素进行快速,便捷的存储,检索,管理,即增删改查CRUD。下图是类和接口的一个总览图,这里先放在此处留哥眼熟,后续会慢慢了解。
2024-12-30 18:48:12
821
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人