首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

《Head First 设计模式》学习心得笔记

工厂模式 工厂方法模式:让子类决定该创建的对象是什么,达到将对象创建的过程进行封装的目的。...调用命令对象的 execute() 方法,即可以令接收者 (Receiver) 执行相关的动作;undo() 方法也可以实现撤销动作; 具体命令对象 (ConcreteCommand):命令对象 (Command...客户使用适配器的过程: 首先,客户通过目标接口,调用适配器的方法,对适配器发出请求; 然后,适配器使用被适配者接口把请求转换成被适配者的一个或多个调用接口; 最后客户接收到调用的结果; 在该过程中...模板方法模式 模板方法模式:在一个方法中定义一个算法的步骤,而将某些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。...当子类必须提供算法中的某个方法或步骤的实现时,使用抽象方法;如果算法的这个部分是可选的,就用钩子(钩子即为在抽象类中,什么事情都不做的一个具体方法,可以让子类有能力对算法的不同点进行挂钩,且由子类自行决定是否需要挂钩

54430

浅析 synchronized 底层实现与锁相关 | Java

用户态、内核态与上下文切换到底是什么鬼? 什么叫自旋锁,它与 CAS 的关系? 对象头是什么玩意,什么又是 MarkWord ?...上下文切换 在jdk1.6之后,synchronizrd 得到了优化,而添加各种锁的目的都是为了避免直接加锁而导致的上下文切换从而引发的耗时浪费。...当到达全局安全点(safepoint)时,获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。 执行同步代码。 偏向锁的释放 偏向锁的撤销在步骤4中已经提过。...适用场景 始终只有一个线程在执行代码块,在它没有执行完释放锁之前,没有其他线程去执行同步块,在锁无竞争的情况下使用,一旦有了竞争就升级为轻量级锁,升级为轻量级锁的时候需要撤销偏向锁,撤销偏量锁的时候会导致...在有锁的竞争时,偏向锁会做很多额外操作,尤其是撤销偏向锁的时候会导致进入安全点,而安全点会导致 stw,导致性能下降。 Stop the word是什么?

34130
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    一道题目带你搞懂回溯算法

    昨天看到一道回溯算法题目,非常烧脑,不过我很喜欢这种感觉,程序员应该定期刷一刷算法题,只有刷算法题目的时候,我才觉得那是真正意义上的编程,平时的工作在多数情况下,都是熟练调用编程语言或框架的 API 而已...其实不难理解,看上图决策树的最左边的分支,当遍历到 2.5.5.2 发现不合适的时候,需要回溯到 2.5.5,然后选择 25,也就是说最后的 2 加入 tmp_list 之后,判断不合适,递归返回之后,...本文提到的回溯算法,本质就是暴力遍历多叉树(本题是 3 叉树)求解,先确定决策树,写出多叉树的遍历框架,然后填充内容。不要忘记在递归完成后撤销选择。...其实这样的回答是错的,无论哪一种遍历,都是要先访问根节点的,不访问根节点,你怎么可能访问得到子节点? 真正的区别在于对根节点的处理是放在进入子节点的递归调用之前,还是在递归调用之后。...前序遍历的代码在进⼊某⼀个节点之前的那个时间点执⾏,后序遍历代码在离开某个节点之后的那个时间点执⾏,如下图所示: ?

    45920

    关于回溯算法,你该了解这些!

    「所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数」。 回溯法的效率 回溯法的性能如何呢,这里要和大家说清楚了,「虽然回溯法很难,很不好理解,但是回溯法并不是什么高效的算法」。...:一个N个数的集合里有多少符合条件的子集 棋盘问题:N皇后,解数独等等 「相信大家看着这些之后会发现,每个问题,都不简单!」...但后面的回溯题目的讲解中,为了方便大家理解,我在一开始就帮大家把参数确定下来。...backtracking这里自己调用自己,实现递归。...总结 本篇我们讲解了,什么是回溯算法,知道了回溯和递归是相辅相成的。 接着提到了回溯法的效率,回溯法其实就是暴力查找,并不是什么高效的算法。

    1.5K41

    回溯算法详解(修订版)

    for 选择 in 选择列表: 做选择 backtrack(路径, 选择列表) 撤销选择 其核心就是 for 循环里面的递归,在递归调用之前...「做选择」,在递归调用之后「撤销选择」,特别简单。...什么叫做选择和撤销选择呢,这个框架的底层原理是什么呢?下面我们就通过「全排列」这个问题来解开之前的疑惑,详细探究一下其中的奥妙!...,他们只是两个很有用的时间点,我给你画张图你就明白了: 前序遍历的代码在进入某一个节点之前的那个时间点执行,后序遍历代码在离开某个节点之后的那个时间点执行。...(选择) 将该选择再加入选择列表 我们只要在递归之前做出选择,在递归之后撤销刚才的选择,就能正确得到每个节点的选择列表和路径。

    42030

    【数据结构与算法】递归、回溯、八皇后 一文打尽!

    在每次递归调用时,都会改变地图的状态,标记已经走过的路径,以及死路。...方法: 定义问题的解空间:确定问题的解可以表示为一棵树的结构,每个节点代表一个可能的解,通过在树上进行深度优先搜索来遍历所有可能的解。 定义候选集:确定每个节点的子节点是什么。...在每个节点上,递归函数检查当前节点的选择是否满足不攻击的条件,如果是,则将其添加到结果集中。然后,递归地调用自身来继续探索下一行的选择。...在每个节点上,递归函数检查当前节点的选择是否满足不攻击的条件,如果是,则将其添加到结果集中。然后,递归地调用自身来继续探索下一行的选择。...具体步骤如下: 初始化一个长度为 8 的一维数组 arr,将其所有元素初始化为 0 从第一行开始逐行放置皇后,调用递归函数 backtrack(arr, 0),其中第二个参数表示当前放置的行数。

    27110

    开启偏向锁一定性能更好吗?

    二、偏向锁 偏向锁是Java 6之后加入的一种针对加锁操作的优化手段,它是基于:在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得。...如果需要撤销,则等待原来的线程进入安全点(safepoint),然后暂停它,并清除对象头和栈帧中的相关信息。撤销之后重新竞争获取轻量级锁。...详情参见:《HashCode方法的调用对Java锁的影响》 四、偏向锁性能更好? 通过前面的介绍,我们不难知道: 偏向锁性能更好的情况是,当一个对象只有一个线程访问,并且不会有其他线程竞争该对象时。...Java在JDK1.6 以后默认已经开启了偏向锁这个优化,JDK15 中,偏向锁被默认禁用了,偏向锁带来的加锁时性能提升从实际效果上看并不明显,不再推荐使用,最终将被废弃。...但工作中真正遇到疑难杂症时,还是这些造火箭的知识更能解决问题。 学习不是目的,学习的目的还是为了:”学以致用“。 大家学习某个技术时,要了解某项技术解决什么问题,优缺点是什么。

    28330

    锁机制-java面试

    偏向锁的目的是在某个线程获得锁之后,消除这个线程锁重入(CAS)的开销,看起来让这个线程得到了偏护。...偏向锁的设置 关闭偏向锁:偏向锁在Java 6和Java 7里是默认启用的,但是它在应用程序启动几秒钟之后才激活,如有必要可以使用JVM参数来关闭延迟-XX:BiasedLockingStartupDelay...可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。...对于自旋锁来说: 1、若有同一线程两调用lock() ,会导致第二次调用lock位置进行自旋,产生了死锁 说明这个锁并不是可重入的。...(在lock函数内,应验证线程是否为已经获得锁的线程) 2、若1问题已经解决,当unlock()第一次调用时,就已经将锁释放了。实际上不应释放锁。

    91260

    【C++】算法集锦(3):回溯,从入门到入土,七道试题精选、精讲、精练

    ; 4、因此在回到上一层结点的过程中,需要撤销上一次选择,这个操作也称之为“状态重置”; 5、深度优先遍历,可以直接借助系统栈空间,为我们保存所需要的状态变量,在编码中只需要注意遍历到相应的结点的时候...,状态变量的值是正确的,具体的做法是:往下走一层的时候,path 变量在尾部追加,而往回走的时候,需要撤销上一次的选择,也是在尾部操作,因此 path 变量是一个栈。...---- 解回溯题的一般步骤 第 1 步都是先画图,画图是非常重要的,只有画图才能帮助我们想清楚递归结构,想清楚如何剪枝。...例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的结果,应该提前剪枝,剪枝的条件是什么,代码怎么写?...index == digits.size()) { ans.push_back(current); return; } //递归调用

    38320

    一文学会「回溯搜索算法」解题技巧

    但它与 “二分查找” 、 “线性查找” 等 “查找问题” 不同的是,“搜索问题” 完成一件事情有可能多种方法,而每一种方法又有多个步骤,回溯算法就是在不断尝试,以得到待求问题的全部的解。...此处我们来认识 path 变量作为状态变量,它在深度优先遍历中的变化:往下走一层的时候,path 变量在尾部追加一个数字,而往回走的时候,需要撤销上一次的选择,这一操作也是在 path 的尾部去掉一个数字...这里需要说明的一点是: 在 Java 语言中,方法传递都是值传递。对象类型的变量在传参的过程中,复制的都是变量的地址。...2、(只与 Java 语言相关)ArrayList 是 Java 中的动态数组,Java 建议我们如果一开始就知道这个集合里需要保存元素的大小,可以在初始化的时候直接传入。...例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的结果,应该提前剪枝,剪枝的条件是什么,代码怎么写? ? 五分钟学算法:思维导图 回溯算法基础问题列表 题目 提示 47.

    1.2K10

    【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练

    ; 4、因此在回到上一层结点的过程中,需要撤销上一次选择,这个操作也称之为“状态重置”; 5、深度优先遍历,可以直接借助系统栈空间,为我们保存所需要的状态变量,在编码中只需要注意遍历到相应的结点的时候...,状态变量的值是正确的,具体的做法是:往下走一层的时候,path 变量在尾部追加,而往回走的时候,需要撤销上一次的选择,也是在尾部操作,因此 path 变量是一个栈。...解回溯题的一般步骤 第 1 步都是先画图,画图是非常重要的,只有画图才能帮助我们想清楚递归结构,想清楚如何剪枝。就拿题目中的示例,想一想人手动操作是怎么做的,一般这样下来,这棵递归树都不难画出。...例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的结果,应该提前剪枝,剪枝的条件是什么,代码怎么写?...index == digits.size()) { ans.push_back(current); return; } //递归调用

    45540

    回溯算法牛逼!

    回溯算法的技巧也不难,前文 回溯算法框架套路 说过,回溯算法就是穷举一棵决策树的过程,只要在递归之前「做选择」,在递归之后「撤销选择」就行了。 但是,就算暴力穷举,不同的思路也有优劣之分。...if 分支,就可以减少递归调用的次数,一定程度上减少时间复杂度。...如果我们提前对nums数组排序,把大的数字排在前面,那么大的数字会先被分配到bucket中,对于之后的数字,bucket[i] + nums[index]会更大,更容易触发剪枝的 if 条件。...的语言特性,这段代码通过先升序排序再反转,达到降序排列的目的。...三、以桶的视角 文章开头说了,以桶的视角进行穷举,每个桶需要遍历nums中的所有数字,决定是否把当前数字装进桶中;当装满一个桶之后,还要装下一个桶,直到所有桶都装满为止。

    49420

    剑指Offer题解 - Day63

    这也就是所谓的剪枝。可以考虑字符串'abb' ,当遍历到第二个'b'时,很明显是重复的,因此不需要字符拼接。而集合的目的就于防止重复的遍历。 如果当前元素不重复,那么就加入到集合中。...注意循环的条件,i的起始值取决于参数x ,而x代表着当前哪个字符是固定的。循环的目的就是将固定位置之后的每个元素分别放到该固定位置上。 然后继续固定下一个位置。...当回溯的时候,需要撤销刚才的元素交换,否则原字符串分隔的元素位置就会被改变。...总结 本题考查字符串的搜索与回溯。难度系数为困难。核心逻辑在于从头开始固定元素,并依次将后续元素与之交换,达到排列的目的。然后递归处理后续元素进行固定和交换。...递归使用的调用栈大小为O(n) ,每次递归需要声明集合,总体来看,空间复杂度是O(n^2) 。

    15020

    搞定大厂算法面试之leetcode精讲11剪枝&回溯

    坐标,然后继续下一层遍历,完成下一层之后,尝试回溯当前层,也就是撤销当前层放置的皇后,同时撤销三个可以攻击到的set坐标,不断回溯,直到遍历完成,找到所有可能的解。...空间复杂度:O(N),其中 N 是皇后数量,空间复杂度主要取决于递归调用层数、记录每行放置的皇后列下标的数组以及三个集合,递归调用层数不会超过 N,数组的长度为 N,每个集合的元素个数都不会超过 N。...,每层循环将nums中的元素加入path中,然后递归调用回溯函数,调用完成之后,回溯之前的状态,当path数组的长度和nums的长度相同就找到了一种排列。...path,然后startIndex加1,继续递归函数进入下一个分支,完成调用之后回溯状态,当path的长度等于k的时候终止这层分支,加入结果中。...子集 (medium) 思路:回溯函数传入字符开始的位置startIndex,不断递归,每一层startIndex加1,当一个分支结束之后在,开始回溯,进入另一个分支。

    54820

    面霸篇:17 张图带你掌握 synchronized 原理

    运行完成之后再将锁状态设置为解锁。 对于 get() 方法也是如此。 Java 中的 synchronized 关键字就是基于这种思想设计的。在 synchronized 关键字中,锁就是一个对象。...在 JVM 进行方法调用时,当发现调用的方法被 ACC_SYNCHRONIZED 修饰,则会先尝试获得锁。...如果一致,继续下一步的判断,如果不一致,跳转到步骤4; 判断是否需要重偏向,重偏向逻辑在后面一节批量重偏向和批量撤销会说明。...当生产者线程创建了大量对象并执行加偏向锁的同步操作,消费者对对象使用之后,会产生大量偏向锁执行和偏向锁撤销的问题。...第一部分是指向栈中的锁记录的指针,第二部分是锁标记位,针对轻量级锁该标记位为 00。 小艾问:那这指向栈中的锁记录的指针是什么意思呢? 小牛答:这得结合轻量级锁的上锁步骤来慢慢讲。

    69330

    回溯,不难!

    一般来说,回溯算法的思考步骤如下: 1、画出递归树,找到状态变量(回溯函数的参数) 2、寻找结束条件,由于回溯算法是借助递归实现,所以也就是去寻找递归终止条件 3、确定选择列表,即需要把什么数据存储到结果里面...4、判断是否需要剪枝,去判断此时存储的数据是否之前已经被存储过 5、做出选择,递归调用该函数,进入下一层继续搜索 6、撤销选择,回到上一层的状态 翻译成代码为如下的形式,也就是回溯算法解题的一个模板:...if ("终止条件") { // 一些逻辑操作(可有可无,视情况而定) // 比如,在 N 皇后问题中,在这一步把数据加入到了结果里面 return...// 一些逻辑操作(可有可无,视情况而定) // 4、判断是否需要剪枝,去判断此时存储的数据是否之前已经被存储过 // 5、做出选择,递归调用该函数,进入下一层继续搜索...// 递归 backtrack("新的参数"); // 一些逻辑操作(可有可无,视情况而定) // 6、撤销选择,回到上一层的状态

    53440

    synchronized的实现原理

    当方法调用时,调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先持有管程,然后再执行方法,最后在方法完成(无论是正常完成还是非正常完成)时释放管程。...为了保证在方法异常完成时monitorenter和monitorexit指令依然可以正确配对执行,编译器会自动产生一个异常处理器,这个异常处理器声明可处理所有的异常,它的目的就是用来执行monitorexit...那Monitor到底是什么?一个作为锁的对象是什么样的工作机制?...所有的Java对象是天生的Monitor,每一个Java对象都有成为Monitor的潜质,因为在Java的设计中 ,每一个Java对象自打娘胎里出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁...偏向锁的撤销需要等待全局安全点。         1)首先暂停持有偏向锁的线程。         2)撤销偏向锁,恢复到无锁状态或轻量级锁状态。

    38530

    【地铁上的设计模式】--行为型模式:命令模式

    如何实现命令模式 命令模式的实现步骤如下: 定义命令接口:定义一个命令接口,该接口包含执行命令和撤销命令两个方法。 创建具体命令类:实现命令接口,包含一个接收者对象以及执行命令和撤销命令的具体实现。...撤销命令:调用者对象调用具体命令对象的撤销方法,从而撤销对接收者对象的操作。 以上是命令模式的基本步骤,通过将请求与实现解耦,将请求封装成对象,从而实现了请求的发送者和接收者之间的解耦。...Java实现 以下是一个简单的 Java 实现示例: 首先,我们需要定义命令接口 Command,它包含了执行命令的方法 execute()。...Invoker 是调用者,负责接收命令,并执行命令。在 ExecuteCommand() 方法中,调用 command.Execute() 实现命令的执行。...总结 命令模式是一种行为型设计模式,其目的是将一个请求封装为一个对象,从而使不同的请求可以被多个对象处理。命令模式中包含三种主要角色:命令接口、具体命令和命令执行者。

    32020
    领券