- 博客(59)
- 资源 (2)
- 收藏
- 关注
原创 java线程池和lock与原子访问
每一个线程的启动和结束都是比较消耗时间和占用资源的。如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢。为了解决这个问题,引入线程池这种设计思想。线程池的模式很像生产者消费模式,消费的对象是一个一个的能够运行的任务线程池的思路和生产者消费模式是很接近的。1. 准备一个任务容器2. 一次性启动10个 消费者线程3. 刚开始任务容器是空的,所以线程都wait在上面。4. 直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒notify5. 这
2022-06-04 14:38:11
239
1
原创 java线程的死锁和交互
演示死锁1. 线程1 首先占有对象1,接着试图占有对象22. 线程2 首先占有对象2,接着试图占有对象13. 线程1 等待线程2释放对象24. 与此同时,线程2等待线程1释放对象1线程代码如下:练习-死锁 3个同步对象a, b, c3个线程 t1,t2,t3故意设计场景,使这3个线程彼此死锁2JAVA 线程之间的交互 WAIT和NOTIFY线程之间有交互通知的需求,考虑如下情况:有两个线程,处理同一个英雄。一个加血,一个减血。减血的线程,发现血量=1,就停止减血,直到加
2022-06-03 23:35:02
241
原创 Sentinel 规则持久化
修改OrderService,让其监听Nacos中的sentinel规则配置。具体步骤如下:在order-service中引入sentinel监听nacos的依赖:在order-service中的application.yml文件配置nacos地址及监听的配置信息:二、修改sentinel-dashboard源码SentinelDashboard默认不支持nacos的持久化,需要修改源码。解压课前资料中的sentinel源码包:然后并用IDEA打开这个项目,结构如下: 在sentinel-d
2022-06-01 20:56:38
229
原创 微服务保护
微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被阻塞。此时,其它不依赖于服务I的业务似乎不受影响。但是,依赖服务I的业务请求被阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞:服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,那么当前服务也就不可用了。那么,依赖于当前服务的其它服务随着时间的推移,最终也
2022-06-01 20:48:36
221
原创 springboot AOP的使用
AOP: 面向切面编程。springboot中使用AOP第一步:首先导入两个依赖<!--springboot自带的aop--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>第二步:定义切面类。为什么使
2022-05-20 16:40:14
6553
2
原创 二叉树的层序遍历
1二叉树的层序遍历层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。使用队列实现二叉树广度优先遍历,动画如下:代码实现如下: //二叉树的层次遍历 public static class Solution3{
2022-05-20 16:05:57
665
原创 二叉树的迭代遍历
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。前序遍历(迭代法)我们先看一下前序遍历。前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。动画如下:所以代码如下:1节点类public class TreeNod.
2022-05-17 23:52:01
97
原创 二叉树的递归遍历:
这里帮助大家确定下来递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法! 确定递归函数的参数和返回值:确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。 确定终止条件:写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。 确定单..
2022-05-16 21:57:15
114
原创 单调栈java算法
比如说,输入一个数组 nums = [2,1,2,4,3],你返回数组 [4,2,4,-1,-1]。解释:第一个 2 后面比 2 大的数是 4; 1 后面比 1 大的数是 2;第二个 2 后面比 2 大的数是 4; 4 后面没有比 4 大的数,填 -1;3 后面没有比 3 大的数,填 -1。这道题的暴力解法很好想到,就是对每个元素后面都进行扫描,找到第一个更大的元素就行了。但是暴力解法的时间复杂度是 O(n^2)。这个问题可以这样抽象思考:把数组的元素想象成并列站立的人,元素大小想象成人的身高。
2022-05-12 21:32:49
446
1
原创 分布式搜索引擎03
0.学习目标1.数据聚合**聚合(aggregations)**可以让我们极其方便的实现对数据的统计、分析、运算。例如:什么品牌的手机最受欢迎?这些手机的平均价格、最高价格、最低价格?这些手机每月的销售情况如何?实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。1.1.聚合的种类聚合常见的有三类:**桶(Bucket)**聚合:用来对文档做分组TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组Date
2022-05-12 20:11:12
124
原创 常数时间删除/查找数组中的任意元素
1时间插入、删除和获取随机元素这些问题的一个技巧点在于,如何结合哈希表和数组,使得数组的删除操作时间复杂度也变成 O(1)?下面来一道道看。代码如下:class RandomizedSet { List<Integer> list=new ArrayList<>(); Map<Integer,Integer> map= new HashMap<>(); Random random= ne.
2022-05-11 20:27:15
299
原创 分布式搜索引擎02
在昨天的学习中,我们已经导入了大量数据到elasticsearch中,实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。所以今天,我们研究下elasticsearch的数据搜索功能。我们会分别使用DSL和RestClient实现搜索。0.学习目标1.DSL查询文档elasticsearch的查询依然是基于JSON风格的DSL来实现的。1.1.DSL查询分类Elasticsearch提供了基于JSON的DSL(Domain Specific L
2022-05-11 19:48:21
187
原创 带权重的随机选择算法和田忌赛马背后的算法决策
1带权重的随机算法解法代码就比如这个 preSum 数组,你觉得随机数 target 应该在什么范围取值?闭区间 [0, 7] 还是左闭右开 [0, 7)?都不是,应该在闭区间 [1, 7] 中选择,因为前缀和数组中 0 本质上是个占位符,仔细体会一下:int n = preSum.length;// target 取值范围是闭区间 [1, preSum[n - 1]]int target = rand.nextInt(preSum[n - 1]) + 1;接下.
2022-05-10 22:02:12
200
原创 分布式搜索引擎01
0.学习目标1.初识elasticsearch1.1.了解ES1.1.1.elasticsearch的作用elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 在打车软件搜索附近的车 1.1.2.ELK技术栈elasticsearch结合kibana、Logstash、Beats,也.
2022-05-10 20:47:03
122
原创 二分搜索的学习
一、寻找一个数(基本的二分搜索)这个场景是最简单的,可能也是大家最熟悉的,即搜索一个数,如果存在,返回其索引,否则返回 -1框架代码:int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(left <= right) { int mid = left + (right - left) / 2;
2022-05-09 20:49:09
91
原创 RabbitMQ的学习
1.初识MQ1.1.同步和异步通讯微服务间通讯有同步和异步两种方式:同步通讯:就像打电话,需要实时响应。异步通讯:就像发邮件,不需要马上回复。两种方式各有优劣,打电话可以立即得到响应,但是你却不能跟多个人同时通话。发送邮件可以同时与多个人收发邮件,但是往往响应会有延迟。1.1.1.同步通讯我们之前学习的Feign调用就属于同步方式,虽然调用可以实时得到结果,但存在下面的问题:总结:同步调用的优点: 时效性较强,可以立即得到结果 同步调用的问题:
2022-05-09 20:32:53
99
原创 RabbitMQ部署指南
1.单机部署我们在Centos7虚拟机中使用Docker来安装。1.1.下载镜像方式一:在线拉取docker pull rabbitmq:3-management方式二:从本地加载自己下载安装包上传上传到虚拟机中后,使用命令加载镜像即可:docker load -i mq.tar1.2.安装MQ执行下面的命令来运行MQ容器:docker run \ -e RABBITMQ_DEFAULT_USER=itcast \ -e RABBITMQ_DEF
2022-05-09 20:09:11
94
原创 Docker学习2
3.1.镜像结构镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。我们以MySQL为例,来看看镜像的组成结构:简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。我们要构建镜像,其实就是实现上述打包的过程。3.2.Dockerfile语法构建自定义的镜像时,并不需要一个个文件去拷贝,打包。我们只需要告诉Docker,我们的镜像的组成,需要哪些BaseImage、需要拷贝什么文件、需.
2022-05-06 16:51:16
184
原创 滑动窗口算法举一反三
本题思路:我们在字符串S中使用双指针中的左右指针技巧,初始化left = right = 0,把索引左闭右开区间[left, right)称为一个「窗口」。PS:理论上你可以设计两端都开或者两端都闭的区间,但设计为左闭右开区间是最方便处理的。因为这样初始化left = right = 0时区间[0, 0)中没有元素,但只要让right向右移动(扩大)一位,区间[0, 1)就包含一个元素0了。如果你设置为两端都开的区间,那么让right向右移动一位后开区间(...
2022-05-05 22:12:55
155
原创 Docker学习1
1.初识Docker1.1.什么是Docker微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。 在数百上千台服务中重复部署,环境不一定一致,会遇到各种问题 1.1.1.应用部署的环境问题大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题: 依赖关系复杂,容易出现兼容性问题 开发、测试、生产环境有差异 例如一个项目中,部署时需要依赖于node.js、Redi
2022-04-27 22:15:09
161
原创 CentOS7安装Docker.DockerCompose及搭建Docker镜像仓库
0.安装DockerDocker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。Docker CE 分为 stable test 和 nightly 三个更新频道。官方网站上有各种环境下的 安装指南,这里主要介绍 Docker CE 在 CentOS上的安装。1.CentOS安装DockerDocker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10, CentOS 7
2022-04-27 21:58:33
292
原创 遍历二维数组的一些技巧
顺/逆时针旋转矩阵题目很好理解,就是让你将一个二维矩阵顺时针旋转 90 度,难点在于要「原地」修改,函数签名如下void rotate(int[][] matrix)如何「原地」旋转二维矩阵?稍想一下,感觉操作起来非常复杂,可能要设置巧妙的算法机制来「一圈一圈」旋转矩阵:但实际上,这道题不能走寻常路,在讲巧妙解法之前,我们先看另一道谷歌曾经考过的算法题热热身:给你一个包含若干单词和空格的字符串s,请你写一个算法,原地反转所有单词的顺序。比如说,给你输入这样一个字符串:...
2022-04-27 21:12:04
1368
1
原创 Gateway服务网关
Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。3.1.为什么需要网关Gateway网关是我们服务的守门神,所有微服务的统一入口。网关的核心功能特性: 请求路由 权限控制 限流 架构图:权限控制:网关作为微服务入口,需要
2022-04-26 21:50:47
153
原创 差分数组的应用
一个和前缀和思想非常类似的算法技巧「差分数组」,差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。比如说,我给你输入一个数组 nums,然后又要求给区间 nums[2..6] 全部加 1,再给 nums[3..9] 全部减 3,再给 nums[0..4] 全部加 2,再给…一通操作猛如虎,然后问你,最后 nums 数组的值是什么?常规的思路很容易,你让我给区间 nums[i..j] 加上 val,那我就一个 for 循环给它们都加上呗,还能咋样?这种思路的时间复杂度是 O(N),由
2022-04-26 20:56:39
396
原创 SpringCloud实用篇02
2.Feign远程调用先来看我们以前利用RestTemplate发起远程调用的代码:存在下面的问题:•代码可读性差,编程体验不统一•参数复杂URL难以维护Feign是一个声明式的http客户端,官方地址:GitHub - OpenFeign/feign: Feign makes writing java http clients easier其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。2.1.Feign替代RestTemplateFegin的使用.
2022-04-25 22:03:30
97
原创 前缀和数组
一维数组中的前缀和这道题的最优解法是使用前缀和技巧,将sumRange函数的时间复杂度降为O(1),说白了就是不要在sumRange里面用 for 循环核心代码如下class NumArray { // 前缀和数组 private int[] preSum; /* 输入一个数组,构造前缀和 */ public NumArray(int[] nums) { // preSum[0] = 0,便于计算累加和 preSum...
2022-04-25 21:32:35
175
原创 如何判断回文链表
题目如下解题思路:首先我们找到该链表的中点节点ListNode slow, fast;slow = fast = head;while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next;}// slow 指针现在指向链表中点如果fast指针没有指向null,说明链表长度为奇数,slow还要再前进一步if (fast != nul.
2022-04-22 21:54:21
341
原创 如何 K 个一组反转链表
思路:这个问题经常在面经中看到,而且力扣上难度是 Hard,它真的有那么难吗?对于基本数据结构的算法问题其实都不难,只要结合特点一点点拆解分析,一般都没啥难点。下面我们就来拆解一下这个问题。一、分析问题首先,前文学习数据结构的框架思维提到过,链表是一种兼具递归和迭代性质的数据结构,认真思考一下可以发现这个问题具有递归性质。什么叫递归性质?直接上图理解,比如说我们对这个链表调用reverseKGroup(head, 2),即以 2 个节点为一组反转链表:如果我设法把前...
2022-04-22 21:44:20
2180
原创 SpringCloud实用篇02
0.学习目标1.Nacos配置管理Nacos除了可以做注册中心,同样可以做配置管理来使用。1.1.统一配置管理当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会让人抓狂,而且很容易出错。我们需要一种统一配置管理方案,可以集中管理所有实例的配置。Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。1.1.1.在nacos中添加配置文件如何在nacos中管理配置呢?然后在弹出的表单..
2022-04-21 22:54:14
82
原创 Nacos集群搭建
1.集群结构图官方给出的Nacos集群图:其中包含3个nacos节点,然后一个负载均衡器代理3个Nacos。这里负载均衡器可以使用nginx。我们计划的集群结构:三个nacos节点的地址:节点 ip port nacos1 192.168.150.1 8845 nacos2 192.168.150.1 8846 nacos3 192.168.150.1 8847 2.搭建集群搭建集群的基本步骤: .
2022-04-21 22:53:05
337
原创 递归反转链表的一部分
什么叫反转单链表的一部分呢,就是给你一个索引区间,让你把单链表中这部分元素反转,其他部分不变注意这里的索引是从 1 开始的。迭代的思路大概是:先用一个 for 循环找到第 m 个位置,然后再用一个 for 循环将 m 和 n 之间的元素反转。但是我们的递归解法不用一个 for 循环,纯递归实现反转。迭代实现思路看起来虽然简单,但是细节问题很多的,反而不容易写对。相反,递归实现就很简洁优美,下面就由浅入深,先从反转整个单链表说起。一、递归反转整个链表这也是力扣第 206 题「反转链表.
2022-04-20 21:43:21
324
原创 双指针技巧2
单链表的中点力扣第 876 题「链表的中间结点」就是这个题目,问题的关键也在于我们无法直接得到单链表的长度n,常规方法也是先遍历链表计算n,再遍历一次得到第n / 2个节点,也就是中间节点。如果想一次遍历就得到中间节点,也需要耍点小聪明,使用「快慢指针」的技巧:我们让两个指针 slow 和 fast 分别指向链表头结点 head。每当慢指针 slow 前进一步,快指针 fast 就前进两步,这样,当 fast 走到链表末尾时,slow 就指向了链表中点。上述思路的代码实现如...
2022-04-14 23:41:36
215
原创 双指针技巧1
合并两个有序链表:给你输入两个有序链表,请你把他俩合并成一个新的有序链表:核心代码如下:public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next =.
2022-04-13 21:55:36
749
翻译 springcloud微服务1
SpringCloud011.认识微服务随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢?1.0.学习目标了解微服务架构的优缺点1.1.单体架构单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。单体架构的优缺点如下:优点: 架构简单 部署成本低 缺点: 耦合度高(维护困难、升级困难) 1.2.分布式架构分布式架构:根据业.
2022-04-06 21:40:22
189
原创 nacos安装指南
Nacos安装指南1.Windows安装开发阶段采用单机安装即可。1.1.下载安装包在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码:GitHub主页:https://github.com/alibaba/nacosGitHub的Release下载页:Releases · alibaba/nacos · GitHub本课程采用1.4.1.版本的Nacos,课前资料已经准备了安装包:windows版本使用nacos-server
2022-04-06 21:37:44
82
原创 springboot整合jwt与vue的后端管理系统7
角色接口开发:角色的增删改查其实也简单,而且字段这么少,基本上吧菜单的增删改查复制过来,然后把menu改成role,在调整一下就差不多啦。然后有个角色关联菜单的操作,这个我们等下讲讲,先来看代码@RestController@RequestMapping("/sys/role")public class SysRoleController extends BaseController { @PreAuthorize("hasAuthority('sys:role:list')") .
2022-03-18 10:43:42
474
原创 springboot整合jwt与vue的后端管理系统6
接下来我们写一下如何实现增删改查菜单接口开发我们先来开发菜单的接口,因为这3个表:用户表、角色表、菜单表,才有菜单表是不需要通过其他表来获取信息的。比如用户需要关联角色,角色需要关联菜单,而菜单不需要主动关联其他表。因此菜单表的增删改查是最简单的。再回到我们的前端项目,登录完成之后我们通过JWT获取项目的导航菜单和权限,那么接下来我们就先编写这个接口。获取菜单导航和权限的链接是/sys/menu/nav,然后我们的菜单导航的json数据应该是这样的:{ title: '角色管理'
2022-03-17 21:35:44
128
原创 springboot整合jwt与vue的后端管理系统5
然后接着讲解决授权解决授权问题1:我们是在哪里赋予用户权限的?有两个地方:1、用户登录,调用调用UserDetailsService.loadUserByUsername()方法时候可以返回用户的权限信息。 2、接口调用进行身份认证过滤器时候JWTAuthenticationFilter,需要返回用户权限信息问题2:在哪里决定什么接口需要什么权限?Security内置的权限注解:@PreAuthorize:方法执行前进行权限检查 @PostAuthorize:方法执行后进行权限检查
2022-03-15 21:37:58
151
原创 springboot整合jwt与vue的后端管理系统4
接着上章节下面我们做一下身份认证登录成功之后前端就可以获取到了jwt的信息,所以后端进行用户身份识别的时候,我们需要通过请求头中获取jwt,然后解析出我们的用户名,这样我们就可以知道是谁在访问我们的接口啦,然后判断用户是否有权限等操作那么我们自定义一个过滤器用来进行识别jwtJWTAuthenticationFilter代码如下import cn.hutool.core.util.StrUtil;import com.rao.service.SysUserService;imp
2022-03-14 21:50:22
894
原创 springboot整合jwt与vue的后端管理系统3
接着上一次我们这一次将整合spring security 安全框架接下来分析我们项目使用框架的流程流程说明:客户端发起一个请求,进入 Security 过滤器链。 当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 logoutSuccessHandler 登出成功处理。如果不是登出路径则直接进入下一个过滤器。 当到 UsernamePasswordAuthenticationFilter 的时候判断是否为登录路径,如
2022-03-12 15:41:00
435
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人