自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 并发工具【上】——线程池及其操作

摘要: 本文介绍了线程池的基本原理与实现。线程池通过复用已有线程避免频繁创建/销毁的性能开销,体现享元模式思想。JDK的ThreadPoolExecutor采用高3位表示线程池状态(RUNNING、SHUTDOWN等),低29位记录线程数,通过原子变量ctl实现状态和线程数的同步修改。线程池构造方法包含核心参数:核心线程数、最大线程数、任务队列和拒绝策略等,工作流程遵循"核心线程→队列→救急线程→拒绝"的四步策略。Executors工厂方法提供了newFixedThreadPool等常用

2025-06-04 21:40:48 852

原创 乐观锁:高效并发无锁方案

本文介绍了乐观锁的概念及其实现方式。乐观锁假设冲突概率低,采用无锁设计,通过CAS(比较并交换)机制实现原子操作,适用于读多写少场景。核心内容包括:1) 乐观锁与悲观锁的对比;2) CAS原理及其在Java原子类中的应用;3) 原子整数类的使用方法。CAS通过volatile保证可见性,利用CPU指令实现原子操作,避免线程阻塞。相比悲观锁,乐观锁在低冲突场景下性能更优,但在高竞争环境下可能导致频繁重试。

2025-05-31 16:56:56 769

原创 深入解析JMM:Java内存模型与并发编程

主内存(Main Memory)定义:在JMM中,主内存是所有线程共享的内存区域存储内容:存储所有的共享变量(实例字段、静态字段等),约等于JVM堆中真正被多线程共享的部分 + 方法区的静态变量,或者是计算机中的内存(注意内存和外存的区别)特点:1.线程对共享变量的所有操作(读/写)都必须在主内存中进行2.是线程间通信的媒介3.对应于物理内存,但不等同于JVM堆内存工作内存(Working Memory)定义:每个线程私有的内存区域存储内容:存储该线程使用到的变量的主内存副本,约等于。

2025-05-22 18:02:10 640

原创 JUC编程monitor、锁膨胀以及相关关键字

如果某个方法加了锁(本质就是加载obj上),那这个对象就会和一个monitor进行关联 然后有线程执行到临界代码 如果monitor还没主人 就会成为monitor的主人) 注意, 这里的唤醒线程往往是非公平的.在jdk1.6之前,synchronized是直接依赖操作系统的Monitor,也就是管程的,因此每次加锁和释放锁都需要操作系统的帮助,性能很差,因此被称为重量级锁。为了解决这个问题,在jdk1.6之后,加入了一系列的优化,例如偏向锁和轻量级锁。

2025-05-20 17:30:34 778

原创 【牛客刷题记录】【JAVA】栈

如果要出队列,那么就需要判断stack2的情况。人与法国stack2为空,则直接把stack1的元素全放进stack2(相当于顺序反过来),然后再出栈。因此只有一个min是无法工作的,需要一个栈来同时记录,记录的内容为【当前元素入栈时的最小值】如果匹配则出栈,否则不用出栈,最后判断栈是否为空。这样的做法是正确的,不过仍可以优化,因为可能出现(] 这样的情况,其实可以直接退出循环。如果-3出栈,stack2的也进行pop操作,最小值也能被记录。我们的队列元素大小总是非递增的,这样就可以很轻松的获取最大值。

2024-11-05 18:23:28 472

原创 【牛客网刷题记录】【java】二叉树

即如果左子非空,则向左dfs,同时deep+1.右子非空,则向右dfs,同时deep+1. 最后查看max与deep的大小,并且更改max。可以创建空节点pre,前驱用当前节点的左指针指向pre,而pre的右指针指向当前节点,最后将pre指向当前节点。我们的这部分就是中序遍历的操作部分,即上面代码的 其他操作。不难发现,二叉搜索树的中序遍历就是我们最终需要的顺序,因此这题一定会和中序遍历扯上关系。前序遍历的顺序为 根-左-右,中序为左-根-右,后序为左-右-根,因此这些遍历也可以说是先根、中根、后根遍历。

2024-10-01 22:30:13 406

原创 【牛客刷题记录】【JAVA】二分查找

原理就是如果找的值比mid小,那么[mid,R]的内容就不需要再查找了,反之如果大于mid位置的值,则在[L,mid]内的值也不需要再查找。注意,一定会存在峰值,因此不需要我们特殊去判断是否为峰值,结束循环返回结果即可,这样可以让代码非常整洁。如果一个版本已经遍历完但另一个还没有,也可以继续循环,这就相当于遍历完的版本号后面多出的0,因为我们的tmp设置都为0,所以不影响比较。逆序对是指数组中的两个数字,如果它们的原始位置是i和j,且i < j但A[i] > A[j],那么它们就构成一个逆序对。

2024-09-30 23:21:02 1019

原创 【牛客网刷题记录】【java】链表

链接也算快指针的做法,先让快指针走k个(有dummy节点),之后再让slow和fast同时走,即可找到倒数的节点。注意输入样例会有超出链表长度的输入,加入判断语句即可。i

2024-09-23 18:20:29 720

原创 【数据结构】【java】leetcode刷题记录--链表

链表是一种常见的基础数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。在Java中,链表通常用于实现动态数据结构,因为它可以根据需要动态地增加或减少节点。节点结构:链表中的每个元素称为节点(Node),每个节点包含两部分:数据域(存储数据)和指针域(存储下一个节点的地址)动态性:链表的长度不是固定的,可以根据需要动态地增减节点。内存分配:链表中的节点不必在连续的内存地址中,它们可以在内存中的任何位置。

2024-09-06 15:41:13 912

原创 【SQL基础】常用聚合函数、函数以及题目

(Aggregate Function)是一类SQL函数,它对一组数据(通常是表中的多行)进行计算,并返回单个值作为结果。得到的结果只有4. 这在较为简单的情况下是没问题的,但如果涉及到分组查询,那就会得不到正确的结果,因为聚合函数返回的值永远是单值。这样得到的才是每个国家的交易订单数量,也就是US3个,DE1个。联表查询将两个表组合成一个,用时间约束价格对应的数量,然后就是如何把每列的价格和数量相乘,再将每种产品的值加和除以总数量。上述函数都可以和聚合函数一起使用,例如有条件的计算和,就可以使用。

2024-08-29 12:08:01 628

原创 【SQL基础】【leetcode】SQL50题

里的,就可以得到只光顾商店的客人。进行分组,这是因为如果不这样使用,聚合函数返回的结果是一个值,需要用分组进行分开。可以把原始的表分为start表和end表,再进行联表查询,这样就可以计算时间戳的插值,进而使用。)的情况查询出的内容是笛卡儿积,而WHERE的限制条件则是对其的筛选。或者我写的这种隐式链接。是一个用于计算两个日期之间差异的函数,它返回两个日期之间的差异,以天数为单位。这一题的本质就是将两个表合并,得到所需的信息,因此不需要额外的操作了。注意,联表查询得到的结果是一张临时表,而最基础的。

2024-08-26 17:30:51 1502 1

原创 【SQL基础】联表查询、UNION(组合查询)题目

其中,一个 SELECT 语句过滤数量为 100 的行,另一个 SELECT 语句过滤 id 以 BNBG 开头的产品,最后按产品 id 对结果进行升序排序。其中,一个 SELECT 语句过滤数量为 100 的行,另一个 SELECT 语句过滤 id 以 BNBG 开头的产品,最后按产品 id 对结果进行升序排序。【问题】编写 SQL 语句,组合 Products 表中的产品名称(prod_name)和 Customers 表中的顾客名称(cust_name)并返回,然后按产品名称对结果进行升序排序。

2024-08-24 22:56:57 1216

原创 【SQL基础】【牛客网】子查询、联表查询

子查询,也称为嵌套查询,是在另一个 SQL 语句中嵌套的查询。子查询的结果可以被主查询(外部查询)使用,用于满足更复杂的数据检索需求。这样的查询是找department_name=“Sales"的employee的name, 涉及到多张表,因此需要用子查询建立一张新的表,来和现有的表进行操作。子查询常用在 WHERE 子句和 FROM 子句后边:当用于 WHERE 子句时,根据不同的运算符,子查询可以返回单行单列、多行单列、单行多列数据。子查询就是要返回能够作为 WHERE 子句查询条件的值。

2024-08-23 19:15:02 1077

原创 【leetcode面试题】java完成leetcode面试150题

最简单的方法就是创建一个新数组,用空间换时间。将nums1和nums2的小的元素放入新数组中,最后再将新数组的值还给nums1.时间复杂度是O(n+m).但也多出来额外的空间。由于上面会出现额外的空间损耗,所以对代码进行改进。下面的代码是不会出现额外空间的。思路就是将大的先放到nums1的末尾,初始的指针指在nums1和nums2的最后一位(即m-1和n-1),然后从大到小,从后往前填充nums1数组。

2024-08-15 12:45:43 1087

原创 【java】【python】leetcode刷题记录--二叉树

例如,一棵树为1、2、3、4、5(数组表示),那么第一次是1入队,处理完1后,1的子节点也就是2、3入队。处理完2,也就是2的子节点入队,即4、5。如果是要求返回的是一个列表,没有嵌套结构,那就会好做很多,我们就按照上面的流程构造队列然后不断处理即可。前序则是将根节点入栈,后续的结点是按照先右边再左边的顺序入栈(因为我们要先处理左子,因此左子后入栈可以先被pop)。层序遍历用的是队列,每次将一个节点入队,处理完当前节点,则其子节点分别入队,下一轮再处理子节点,也就是下一层的内容。

2024-06-12 22:47:52 625 4

原创 【java】【python】leetcode刷题记录--栈与队列

在Python中,对于整数除法,/ 操作符执行的是真除法(返回浮点结果),而 // 操作符执行的是地板除(即对结果向下取整到最近的整数)。出队操作(使用stackOut):当需要进行出队操作(即移除队列的最前端元素)时,我们先检查stackOut:如果stackOut为空,则将stackIn中所有元素逐一弹出并推入stackOut。queue2是辅助队列,queue1存放进入栈的元素,当想要得到栈顶(队尾)元素,即把queue1的元素放入queue2,知道queue1只剩一个元素,该元素则为栈顶元素。

2024-06-02 22:36:06 947 4

原创 【Java】【python】leetcode刷题记录--双指针

双指针也一般称为快慢指针,主要用于处理链表和数组等线性数据结构。这种技巧主要涉及到两个指针,一个快指针(通常每次移动两步)和一个慢指针(通常每次移动一步)。快指针可以起到’探路‘的作用,给慢指针修改。

2024-05-28 09:55:21 1016 2

原创 【Java】【更新中】java常用操作以及数据结构

【代码】【Java】【更新中】java常用操作以及数据结构。

2024-05-15 21:15:17 443 1

原创 【Java】【python】【数据结构与算法】leetcode刷题记录--哈希表

从上文得知,哈希为我们提供了快速的增删改查的操作,在使用相关的数据结构中,我们不需要考虑hash实际的实现是怎么样的。同时,尽管不同的输入可能会产生相同的输出(这种情况称为哈希冲突),但是在理想情况下,哈希函数应该尽量使这种情况发生的概率最小。哈希是一种将大量信息压缩到较小空间的技术,本质上就是一种映射关系,将复杂的信息映射到对应的哈希表的位置,因此可以提供快速的查找。哈希会提供特点的映射函数(散列函数),例如有大小为5的哈希表,分别为0、1、2、3、4,而每个位置存储的值是模除5等于对应下标的值。

2024-05-14 10:08:14 501

原创 【Java】【数据结构与算法】【华为】leetcode刷题记录--数组、双指针和滑动窗口

本篇博客适用于对于数据结构和算法有一定基础,懂得计算机基础概念(例如内存分配)的人阅读和学习,且本文内容的语言仅有java,如果有需求可以再加上python版本。

2024-05-12 19:49:59 905 3

原创 【python】函数、闭包以及装饰器

而里面的inner可以使用外部函数outer的x变量,这样可以防止全局变量的滥用,而最外层的add_five则是一个闭包。在使用flask框架时,总能发现一个叫route的装饰器,它的主要作用是将函数绑定到一个URL,当flask处理请求的时候,会检查其请求的URL,然后调用与这个URL关联的函数。然而,它们用于解决的问题是不同的:装饰器用于修改函数或类的行为,而闭包用于记住函数的状态。首先,装饰器和闭包都是高阶函数,即它们都是接收函数作为参数或返回函数的函数。是一种简单的表示装饰器的方法。

2024-04-05 18:38:43 321 1

原创 【数据结构】【python】迭代器及其优点

迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器不仅可以用于已知的数据结构,还可以自己构造迭代器。例如,ist 是可迭代对象,dict 也是可迭代对象。print(i)实际上,list是一个可迭代对象,其内部使用python内置函数iter()调用遍历对象的__iter__()获得一个迭代器,之后再循环对这个迭代器使用next()调用迭代器对象的__next__()。iter。

2024-01-30 14:46:01 522 1

原创 【数据结构】【树的遍历算法】【python】树的各种遍历算法

先将根节点入队,再对队列进行循环操作:如果队列未空,则将队头元素弹出,对队头元素操作,并将其子节点放入对内。如果遇到节点不存在的情况,返回值为0,代表深度为0,否则就返回的是左子树和右子树中深度的最大值。,即以当前节点为例,先遍历左子节点,再是当前节点,再是右子节点。的信息,然后再判断是否有右子节点,并再次递归调用,将函数压入栈。的信息,第三个递归函数执行完成,退栈。

2024-01-28 12:01:16 1776 2

原创 【数据结构】【更新中】【python】leetcode刷题记录:热题100答案 + 每日一题(附文字说明)

题目为leetcode的热题100.仅作学习用,且题目为节选。

2024-01-27 12:28:59 2244 2

原创 【计算机组成原理】中断排队次序、中断处理次序和多重中断

中断可以分为硬中断和软中断,一般是外部中断,例如在指令执行到中断周期时检测到有外设的中断请求,则会执行中断隐指令、中断服务程序等一些列操作。(因为上一条指令已经执行完成,中断的部分是由于外部请求)。一般是内部中断,例如缺页,则在指令执行的过程中就可以产生中断,去执行缺页程序。因此,中断在执行完中断隐指令后,需要执行中断服务程序,即。那么如何得到中断服务程序的地址呢?这里需要用到硬件。

2023-12-17 20:30:12 1497 2

原创 【计算机组成原理】【考试速通】第二章数据的运算和表示

每次取Y的最后一位(或者说最低位)乘X内的被乘数,乘积结果的值加到P上,然后P和Y的值整体右移一位,P右移是因为乘法列竖式时,下一次运算的结果比当前的运算结果要高一位,而Y右移不仅是给P腾出空间,也是将下一次和被乘数做乘积的数更新。IEEE的浮点数除去阶码的表示和上面不同之外,其尾数前也加1,这是因为对于规格化的二进制浮点数,尾数的最高位总是1,故1就当作隐藏位,不写在尾数中,最后计算真值的时候加上1即可(前提是阶码不为全0、全1这种特殊情况)。规格化的方法:若是最高位不是1,则需要左移,直到最高位为1。

2023-10-03 17:49:21 785 1

原创 【计算机组成原理】【考试速通】性能衡量标准、机器字长存储字长指令字长、透明性问题

例如,应用程序程序员不需要了解操作系统的内部实现逻辑,那么操作系统对应用程序程序员来说就是透明的(可忽略的)。再或者,计算机系统结构是指对OS程序员、汇编程序员、机器语言程序员不透明的,因为系统结构是和上述程序员的工作相关的。但有一定的缺陷,例如开发人员可以根据测试程序做专门的优化,因此导致测试结果并不能反映实际的处理能力。(4)主频和CPU周期,互为相反数。例如指令执行需要2个时钟周期,而主频高,则周期短,指令执行更快。(1)字长,即一次整数运算能处理的二进制数据的位数,通常和CPU的ALU长度相同。

2023-10-02 21:14:23 321 1

原创 【计算机组成原理】【考试速通】第一章 计算机系统概述

计算机硬件、软件、程序编译、翻译、连接、重定位、冯诺依曼

2023-10-02 18:16:15 189 1

原创 【操作系统】【计算机组成原理】从总线理解IO子系统

本文设计总线、操作系统、计算机组成原理、IO子系统、文件系统、中断、DMA、直接内存访问、IO接口

2023-09-19 22:28:07 577 1

原创 【计算机系统结构】【延迟槽技术】分支延迟、分支预测和MIPS延迟槽

注:本文从系统结构的角度去看待延迟槽这一技术,故不会涉及到代码细节,仅仅描述延迟槽的工作原理。且该文字描述的流水线基于的是经典的MIPS五段流水,即IF、ID、EX、MEM、WB。

2023-06-18 21:35:52 8268 6

原创 文件描述符表、文件打开表和inode表 硬链接与软连接

文件描述符表 文件打开表 inode 文件系统 硬链接 软连接

2023-05-22 15:31:36 940 1

原创 从Ucore分析OS文件系统

文件系统 linux操作系统 ucore 文件管理

2023-05-22 15:16:07 483 1

原创 【LINUX】【北邮】第七章 文件和目录权限、shell的基本机制

文件的权限是用于控制进程对系统中的文件和目录的访问。权限中的写很特殊:不可写但是可以被删除。因为删除文件并不需要写文件。可执行文件一般分为两类:程序文件和脚本文件。程序文件实际上就是CPU指令的集合,例如现在使用的LS等命令实际上就是一些可执行文件。脚本文件存的不是指令,那CPU就不能执行。具体运行的时候是每读取一行就进行一次解释。

2023-04-22 21:57:26 203

原创 【计算机系统结构】 【北邮】第五章 指令并行及其开发——硬件方法 上

MIPS五段流水 硬件方法

2023-04-18 21:46:11 3187 1

原创 UCORE实验二 物理内存管理(动态分区分配、分页、页表)

此函数找到一个线性地址对应的二级页表项的内核虚地址,如果此二级页表项不存在,则分配一个包含此项的二级页表。但与单纯的动态分区分配不同,由于是基于分页的,所以当搜索的分区大小大于所需的内存时,就可以将分区分成两部分,一部分提供给申请的部分,剩下的则形成新的空闲区。应该将操作移至循环内。下图为二级页表结构,在进行地址转换的过程中,先通过线性地址的前10位找到一级页表的entry,内含二级页表的基址,加上中间十位作为偏移量,即可得到二级页表的表项,内含物理页的基址,再加上offset即可得到具体的虚拟地址。

2023-04-17 21:32:15 516 1

原创 UCORE实验一思路 BIOS 段机制 函数调用栈机制 中断机制

关于UCORE BIOS bootloader 段机制 函数调用

2023-04-17 21:05:04 376 1

原创 【北邮面对对象程序设计】 面对对象的主要概念

对象 定义:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组**属性**和对这组属性进行操作的一组**服务**构成。简单来说,一位计算机老师就可以是一个对象,他/她是现实中存在的人,他具有自己的属性:例如180的身高,75kg的体重,熟练java代码等等,可以理解为**静态特征**。而他由于他的属性(写代码),他可以去进行一系列的服务(操作),比如去写一个java的小程序,这是他的**动态特征**。抽象和类继承、消息和聚合抽象类与接口...

2022-03-03 20:31:44 408

空空如也

空空如也

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

TA关注的人

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