自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(52)
  • 资源 (1)
  • 收藏
  • 关注

原创 JUC 系列:AQS -->学习 Doug Lea 大神思想

AQS:全称是AbstractQueuedSynchronizer,一个并发同步管理框架类,是 JUC 的灵魂抽象类。如果要自己去实现一个同步管理框架呢?个人学习寒食君大佬的解析后觉得可以分为三点:通用性,下层实现透明的同步机制,同时给上层提供业务代码编写的功能利用 CAS 操作,原子的修改共享标志位(由这个标志位来判断共享资源是否空闲)等待队列(埋伏笔:情况①:当共享资源被占用时,直接返回结果、情况②:当共享资源被占用时,让后续的线程进入到等待队列中等待)与 AQS 的结构有着异曲同工之妙,

2021-09-08 16:30:25 366

原创 Redis 数据类型--> 字符串解析

闲来无事,去看了下《Redis 设计与实现》这本广受好评的书(确实好,连我这种小白都读得顺畅)。Redis 中的字符串Redis 中的字符串并没有直接使用 C 语言中的字符串,而是自己构建了一种简单动态字符串,并将 SDS 用作 Redis 的默认字符串表示。举个列子,客户端执行命令:resdis> SET msg "hello word",其中:键值对的键是一个字符串对象,对象的底层实现是一个保存着字符串 “msg” 的 SDS。键值对的值也是一个字符串对象,对象的底层实现是一个保存着字

2021-09-07 15:54:27 182

原创 贼详细但又贼容易理解的类加载过程

本文视频:寒食君什么是类加载?众所周知,Java 代码能在各个操作系统上运行起来,靠的是 JVM。Java 文件通过javac编译成class文件,这种中间码被我们称为字节码,然后由 JVM 加载字节码。运行时解释器将字节码解释成一行一行的机器码来执行。在程序运行期间,即时编译器会针对热点代码,直接将该热点代码编译成机器码来获得更高的执行效率。上述的介绍中可以知道这就分为两个部分,编译器我们理解不了,但 JVM 加载字节码这个过程(就是类加载)就需要我们去了解了。类加载的过程类加载过程就只有加载、

2021-07-28 11:41:29 168

原创 Oracle 批量上传或更新操作(速度可观)

Oracle 批量上传或更新操作(这个版本适用于数据量很小的情况下,上万的数据量已经有点慢了)别把 BEGIN 与 END 漏掉了,批量的话得用 <insert id="对应 Mapper 层方法名" parameterType="java.util.List" > BEGIN <foreach collection='list' item='item' separator=';'> MERGE INTO 表名 T USING

2021-07-27 18:01:52 1213

原创 Excel 模板下载功能 + 前、后端解析 Excel 文件代码封装 + 前端上传 Excel 至数据库(SpringBoot + Vue 版)

最近做需求时遇到一个可向导的文件上传功能,现在做完了来分享下,基本能满足大伙80%的需求了一、Excel 模板下载功能后端代码(这是07版的Excel,需要03版的修改 XSSFWorkbook workbook = new XSSFWorkbook(fis); 这行代码即可):public void download(HttpServletResponse response) throws IOException { FileInputStream fis = new FileInputStr

2021-07-16 15:25:51 663

原创 多进程与多线程的区别

今天七牛云的面试被问到了没答好,在此记录下加深印象进程与线程的区别先来说下进程与线程间的区别:进程是一个独立功能的程序,而线程是进程中的其中一个功能(比如:你打开了QQ,QQ就是一个进程。然后你在QQ输入文字聊天,这个就是线程)。进程是系统进行资源分配和调度的单位,而线程是 CPU 调度和分派的基本单位。进程的资源是被线程共享的多进程与多线程的区别多进程的数据是分开的,所以多进程共享复杂,同步简单(需要用IPC);而多线程由于是共享一个线程的资源,所以多线程共享简单,同步复杂。多进程占

2021-06-16 21:58:54 339

原创 Redis 的持久化机制

Redis 有两种持久化机制:RDB 和 AOF,其中 RDB 是 Redis 默认采用的持久化机制。RDB通过BGSAVE(通知当前 Redis 的主进程去fork出一个子进程,利用子进程去做持久化的事)命令触发,以快照的形式将数据持久化到硬盘当中。大致流程如下:BGSAVE命令触发后,如果已经有子进程就会直接返回,没有就会通知父进程去创建一个子进程父进程去创建子进程(fork时会产生阻塞,但时间会比较短暂)子进程创建过后,父进程就继续去响应其他的命令子进程去将父进程内存里的数据存储到 R

2021-06-15 21:36:11 63

原创 设计模式(单例、工厂)

设计模式的六大原则单一原则:一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化。里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能。依赖倒置原则:面向接口编程(通过接口作为参数实现应用场景),抽象就是接口或者抽象类,细节就是实现类。接口隔离:建立单一接口(复杂的接口,根据业务拆分成多个简单接口)。迪米特原则:最少知道原则,尽量降低类与类之间的耦合(一个对象应该对其他对象有最少的了解)。开闭原则:用抽象构建架构,用实现扩展原则。单例模式单例模式就是在整个运行

2021-06-14 15:03:07 1110 2

原创 CMS 垃圾回收器与G1 垃圾回收器

CMS 垃圾回收器CMS(Concurrent Mark Sweep)收集器,以获取最短回收停顿时间(也就是指Stop The World的停顿时间,即轻GC的时间)为目标。其中Concurrent是指垃圾收集的线程和用户执行的线程是可以同时执行的。CMS 垃圾回收器采用的是"标记-清除"算法,整个过程大致分为4个步骤(详细的话有七个步骤):初始标记:即标记一下与GC Roots直接有关联的对象,速度很快。(会触发Stop The World停顿!)并行标记:即垃圾回收的线程与用户的线程可以一起执

2021-05-28 15:33:13 158

原创 在浏览器地址栏输入URL,按下回车后究竟发生了什么?

由于面试中每次都被问到,就记录一下到底发生了什么:一、将域名解析成IP地址进行访问(得到IP地址得过程又分为几步)1.1、去查找浏览器的缓存。因为浏览器在你访问过网站后一般都会个缓存记录,有的话就返回IP地址,没有则下一步。1.2、去查找本地缓存。去查找windows的本地缓存文件hosts,有的话返回IP地址,没有则下一步。1.3、去查找路由器的缓存。一般路由器都有自己的一个缓存,将请求发给路由器,查找ISP 服务商缓存 DNS的服务器,如果查找到IP则直接返回,没有的话继续查找。1.4、本机

2021-05-24 17:42:14 145

原创 Java 多线程(工具篇)

线程池原理线程池的七大参数详解:int corePoolSize:该线程池中核心线程数最大值。核心线程:线程池中有两类线程,核心线程和非核心线程。核心线程默认情况下会一直存在于线程池中,即使这个核心线程什么都不干(铁饭碗),而非核心线程如果长时间的闲置,就会被销毁(临时工)。int maximumPoolSize:该线程池中线程总数最大值 。该值等于核心线程数量 + 非核心线程数量。long keepAliveTime:非核心线程闲置超时时长。非核心线程如果处于闲置状态超过该值

2021-05-23 15:11:40 124

原创 Java 多线程(原理篇)

本文有点长,请慢慢食用…(当然想更清楚还是去看上次推荐的书)Java 内存模型(JMM)JMM的抽象示意图:由图可知:所有的共享变量都存在主内存中。每个线程都保存了一份该线程使用到的共享变量的副本。如果线程A与线程B之间要通信的话,必须经历下面2个步骤:a. 线程A将本地内存A中更新过的共享变量刷新到主内存中去。b. 线程B到主内存中去读取线程A之前已经更新过的共享变量。因为根据JMM的规定,线程对共享变量的所有操作都必须在自己的本地内存中进行,不能直接从主内存中读取。所以,线程.

2021-05-22 15:45:48 286 1

原创 ConcurrentHashMap(八股笔记)

ConcurrentHashMap1、ConcurrentHashMap的存储数据结构在jdk1.8,ConcurrentHashMap 取消了 Segment 分段锁,采用 CAS 和 synchronized 来保证线程安全。数据结构跟 HashMap1.8 的结构类似,Node数组+链表/红黑二叉树。Node数组里存key,value,next字段,hash值(其中value和next都用volatile修饰,保证并发的可见性)。Java 8 在链表长度超过一定阈值(8)时将链表(寻址时间复杂度

2021-05-20 22:09:35 293

原创 Java 多线程(基础篇)

本文记录于阿里一群大佬们手码的书:《深入浅出Java多线程》线程与进程的区别:进程是一个独立的运行环境,而线程是在进程中执行的一个任务进程单独占有一定的内存地址空间,所以进程间存在内存隔离,数据是分开的,数据共享复杂但是同步简单,各个进程之间互不干扰;而线程共享所属进程占有的内存地址空间和资源,数据共享简单,但是同步复杂。进程单独占有一定的内存地址空间,一个进程出现问题不会影响其他进程,不影响主程序的稳定性,可靠性高;一个线程崩溃可能影响整个程序的稳定性,可靠性较低。进程单独占有一定的内存地.

2021-05-19 20:34:20 55

原创 Java常见的3中 IO 模型

本文部分参考 Guide大佬的八股文!!!UNIX 系统下, IO 模型一共有 5 种: 同步阻塞 I/O、同步非阻塞 I/O、I/O 多路复用、信号驱动 I/O 和异步 I/O。BIO (Blocking I/O)BIO 属于同步阻塞 IO 模型。在同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到在内核把数据拷贝到用户空间。同步阻塞:从准备数据到拷贝数据都一直是阻塞的。BIO 在连接数量少时还能应付,当连接数达到百万级别时就不行了,需要换更高效的 IO 模型。NI.

2021-05-19 16:23:43 144 1

原创 一篇文章彻底搞懂 TCP 三次握手、四次挥手

首先看TCP的报文格式:三次握手客户端要给服务端发送一个建立连接的请求(请求里有一个标志位SYN=1,并且会初始化一个32位的随机序列号seq)这时服务器就知道客户端要建立一个连接,然后就会回一个东西(有标志位SYN=1,随机生成一个32位的序列号,ACK=1,消息确认序号ack包,ack=seq+1(这个操作是为了告诉服务端,下次发的报文需要从ack开始))通过这两步,客户端就知道服务端知道自己要连接它了,但是服务端不知道客户端收到了它发的确认消息,所以客户端还需要再发送一次消息,以保证连接

2021-05-10 22:26:31 202 1

原创 Java 常用集合类的底层扩容机制

集合里的三大接口:List、Set、Map,其中 List 与 Set 继承于 Collection 接口(Collection 继承于 Iterable 接口)。ListArrayList 底层扩容机制先说结论:它的底层使用的是一个Object类型的数组 elmentData [];当创建一个ArrayList时,如果没定义初始容量大小,则elmentData [] 为0。当添加了第一个元素进去后,elmentData [] 默认扩容为10,如需再次扩容,则扩容 elmentData [] 为

2021-05-06 22:35:54 322 1

原创 削峰、限流与防刷

削峰(大闸)限流(限流器+队列)方案为了承载高并发,就要用到一些技术组合,这里记录下削峰限流组合的方案流程。下单前先去验证下,目的是交易是为了让有权限的人来交易,而一下子来了1000人,结果只有100人有权限,如果让这1000人都先去交易再看有权限没有,就会很浪费性能。因此可以提前筛选下,让验证通过的直接交易就可以了。所以现在削减流量的环节就可以放在验证上了,大致流程如下:用户验证后就会获得一个令牌,有这个令牌就可以交易。但是令牌的发放量也得有限制。因为有权限的人肯定比可交易量大,所以令牌就限制

2021-05-02 17:25:46 1184

原创 RocketMQ 事务型消息 + 异步扣减库存实现

Rocket 事务型消息事务型消息为了保证最终一致性(就是本地执行的事务与消费者的消费操作保持原子性)会用到两阶段提交,这里就简单记录下其中的过程。图解:生产者(Preducer)、消费者(Consumer)、代理服务器(Broker,因为 Broker 会有 Name Server 来绑定,所以这里就简称MQ Server)和 数据库 MySQL。两阶提交段步骤:首先,消费者会发送一个半成品消息给代理(不让消费者去消费),然后代理会给消费者返回一个 OK 。本地执行事务,消费者这时就会访问

2021-05-01 15:30:44 1770

原创 分布式部署与MySQL读写分离、MySQL分布式事务

分布式部署方案部署多个 Tomcat 服务器,这个就可以用 Nginx 来分发请求给各个服务器,而为了防止单个 Nginx 挂了,这时就可以用热备来再准备个 Nginx,这两个 Nginx 同时去抢请求,没抢到的Nginx就会去监听另一个Nginx(采用心跳监测,就是疯狂Ping它,没返回值的时候就是挂掉了,然后它就可以上位了)。性能优化一、构建二级缓存(本地缓存+Redis)二、通过Redis + RocketMQ 异步处理持久化操作部署图:MySQL 读写分离就是数据库层面为了提高性能,

2021-04-26 23:00:54 304

原创 索引 笔记

索引分类根据MySQL的官网,可将索引分类为:普通索引唯一索引(主键索引就是其中一种)全文索引空间索引根据存储方式可分为:B-Tree 索引(存储数据是有序的!!!)Hash 索引按依赖的列数分为:单例索引组合索引按数据分布可分为:聚簇索引(包含了所有的数据)二级索引按回表情况可分为:覆盖索引(当一个索引包含了需要查询的字段的值时,称其为覆盖索引)最左前缀每行依据索引的顺序来排就是有序的(即先用了范围索引,后面的就不能精确索引了,因为范围后就无序了

2021-04-12 20:37:36 86 1

原创 Spring-SpringMVC-SpringBoot-Mybatis 关联与重点笔记

导语:Spring全家桶是现在非常常用的开发首选脚手架,它们能够帮助我们快速的开发一些Web项目等等,那么Spring与SpringMVC、SpringBoot的之间的关联是怎么样的呢?一个简略的关系图:其实,在开发中Spring+SpringMVC就完全可以了,而SpringBoot只是充当了一个集成者,它简化了我们很多步骤。Spring更侧重的是一个概念,SpringMVC更侧重的是开发的一个流程,SpringBoot则更侧重其功能。SpringBoot其好处用过的知道,怎么一个秒字了得。.

2021-04-11 14:34:14 1124

原创 JUC 常用知识点 4(ForkJoin、Volatile、JMM)

ForkJoinForkJoin就是可以把大任务拆分成几个小任务来执行(含有递归思想!)。ForkJoin的特点:可以工作窃取,即一条线程的任务执行完后可以抢其他线程还没完成得任务来做(它维护的是一个双端队列),这样就可以提升效率。以一个求和实例来看看 FrokJoin 的效率:求和:1-1000000000public class Zeng{ public static void main(String[] args) throws IOException, ExecutionEx

2021-04-09 15:54:09 192

原创 JUC 常用知识 3 (四大函数式接口与Stream 流式计算)

如今程序员必会的四个操作:lambda 表达式、连式编程、函数式接口、Stream 流式计算四大函数式接口即只有一个方法的接口,即类上有注解 @FunctionalInterface 的接口,比如Runnable接口、foreach()等等。在Java中有大量的函数式接口,它可以简化编程模型,在新版本的框架底层大量运用。1、Function 函数式接口有一个输入参数,有一个返回值类型public static void main(String[] args) { Function f

2021-04-09 13:47:48 100

原创 JUC 常用知识 2(线程池)

线程池池化技术由于程序的运行,本质是在占用系统的资源!而为了优化资源的使用,就诞生了池化技术,比如有线程池、常量池、JDBC的连接池…线程池的好处:1、降低资源的消耗2、提高响应的速度3、方便管理4、线程复用,可以控制最大并发数,管理线程线程池:三大方法,七大参数,四种拒绝策略三大方法一、创建单个线程池 => Executors.newSingleThreadExecutor();ExecutorService threadExecutor = Executors.new

2021-04-08 20:16:06 51

原创 JUC 常用知识点 1

三个并发的常用辅助类:1、CountDownLatch可以当做类似一个倒计时计数器来记,一个实例:老师要等教室里的6个学生都走了才能关门 // 倒计时计数器CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 1; i <= 6; i++) { new Thread(()->{ System.out.println("第"+Thread.currentThread().getName()+"个

2021-04-08 15:32:26 79

原创 生产者与消费者的 synchronized版 与 Lock版

导语:在多线程的情况下,为了保证数据安全性,就会使用到锁来保证每个线程之间互不影响,以免引起数据异常。这篇文章就来记录下所遇到的问题…下面用一个多线程实例来了解下两者的区别,实例为:有一个资源类Data,里有只有一个属性number=0,一个 number+1 和一个 number-1 的方法。这时有两个线程A与B,A线程调用加一方法,B线程调用减一方法。要求:必须 number 等于0时才加一,不等于0时才减一,两线程循环执行10次。synchronized版的多线程代码:package.

2021-04-03 17:22:44 64

原创 JVM 学习笔记 2

插一句:JVM有三种,分别是Sun公司的HotSpot VM(现在的常用JVM)、BEA JRockit、IBM的J 9VM。6、堆Heap,一个JVM只有一个堆内存,且堆内存的大小是可以调节的。超出内存会报OOM错误!堆内存中还能细分为三个区域:新生区(又包含伊甸园区、幸存0区、幸存1区,这两个幸存区是动态交换存的)1、类的诞生和成长,甚至被回收的地方2、所有对象都是在伊甸园区new出来的养老区新生区满了后,经过垃圾回收活下来的就进入养老区永久区(jdk1.8后叫元空

2021-04-01 15:19:34 176

原创 JVM 学习笔记 1

JVM简化图简化图地址1、类加载器类加载器的作用就是加载class文件,加载器又分为:虚拟机自带的加载器、启动类(根)加载器、扩展类加载器、应用程序(系统类)加载器。类装载器采用的机制是双亲委派机制。JVM先从AppClassLoader一层一层往上去找2、双亲委派机制AppClassLoader–> 扩展类 ExtClassLoader–> 根加载 Bootstrap classLoader这个机制是为了保证安全的,其原理:在new了一个对象后,它会先从AppClassLoade

2021-03-29 15:14:27 62

原创 Redis (笔记)

基础知识redis是由C语言去写的,可以用作为数据库、缓存和消息中间件MQ,它默认拥有16个数据库,且默认使用的是第0个数据库。redis端口号是6379是因为粉丝效应(redis作者的一个爱豆的名字对应9键)。Redis的五大数据类型 Redis-keyStringListSetHashZsetRedis的三中特殊数据类型geospatail(关于地理位置空间的)hyperloglogbitmaps1、Redis 为什么是单线程的?原因:Redis是很快的,官方表示,Red

2021-03-18 13:49:42 65

原创 Java Integer缓冲区

直接实践得真知吧!实例一: Integer integer1 = new Integer(100); Integer integer2 = new Integer(100); System.out.println(integer1==integer2);实例一的运行结果为 false原因因为这里首先会在栈里创建integer1和integer2,这两个变量里存的值100是在堆里,这里比较的是栈里存的地址是否一样,很明显这是两个不同的对象,地址不一样实例二:

2021-01-31 16:03:31 105

原创 Java 中的字符常量池

Java中的字符常量池Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "wuyang";另一种就是使用new这种标准的构造对象的方法,如String str = new String("wuyang");这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池。工作原理当代码中出现字面量形式创建字

2021-01-29 16:05:53 71

原创 LeetCode 125.验证回文串

解题思路使用双指针,左指针向友移,右指针向左移,判断移动到的字符是否是字母或数字,是就判断是否相同,不是字母或数字则继续移动;终止条件为两指针相遇;时间复杂度:O(|s|)O(∣s∣),其中 |s|∣s∣ 是字符串 ss的长度。空间复杂度:O(|s|)O(∣s∣)。由于我们需要将所有的字母和数字字符存放在另一个字符串中,在最坏情况下,新的字符串与原字符串完全相同,因此需要使用 O(|s|)O(∣s∣) 的空间。代码:class Solution(object): def isPalindr

2021-01-27 16:37:19 51

原创 LeetCode 121、122买卖股票跌得最佳时机

解题思路121、方法一:只能进行一次买卖,则用贪心算法来计算,遍历一遍数组,最大利润就是最大值减去最小值,遍历时不断更新最小值即可代码:class Solution(object): def maxProfit(self, prices): if not prices: return 0 n = len(prices) min_val = float("inf") res = 0 for

2021-01-26 17:57:38 64

原创 LeetCode 15.三数之和

解题思路在两数之和的基础上去解,用排序加双指针即可,先固定第一个值,再用双指针去找另外两个值,如果和大于 0,那就说明 right 的值太大,需要左移。如果和小于 0,那就说明 left 的值太小,需要右移代码:class Solution(object): def threeSum(self, nums): n=len(nums) res=[] if(not nums or n<3): return []

2021-01-24 16:57:33 57 1

原创 LeetCode 83.删除排序链表中的重复元素

解题思路用node来当做当前节点,node.next当做下一节点,用while循环来遍历链表;遍历玩链表挤结束,还需要判断下头结点head与node是否为空,如果遍历过程中当前节点与下一节点相同则删除一个,即 node.next=node.next.next,如不相同则继续遍历代码:class Solution(object): def deleteDuplicates(self, head): node=head while node and node.next:

2021-01-23 16:49:54 60

原创 LeetCode 69.x的平方根

解题思路方法一:调用库来解决代码:import mathclass Solution(object): def mySqrt(self, x): return int(math.sqrt(x))方法二:暴力解法,先假设根为1(自加),再一直判断根的平方是否满足<=x,不满足时返回根-1代码:class Solution(object): def mySqrt(self, x): sqrt=1 while sqrt**2<=x:

2021-01-23 15:35:36 64

原创 LeetCode 58.最后一个单词的长度

解题思路split()函数删除空格再将数组倒序,遍历一遍返回开头不是空格的第一个单词的长度代码:class Solution(object): def lengthOfLastWord(self, s): r = s.split(" ") r.reverse() for i in r: if i: return len(i) return 0...

2021-01-22 16:20:20 54

原创 LeetCode 53.最大子序和

解题思路对于当前数字,若前面的几个数字的和为正,则加上前面的数字组的和作为新的最大子数组,若前面的数字组的和为负则保留自身作为新的最大子数组得开头;每次遍历后都与当前最大子数组和做比较,保留较大者。代码:class Solution: def maxSubArray(self, nums: List[int]) -> int: maxSum = tempSum= nums[0] for num in nums[1:]: tempSu

2021-01-21 16:42:51 51

原创 LeetCode 35.搜索插入位置

解题思路target在nums中,直接遍历查找给下标,不在的话加入nums中排序再给下标代码:class Solution(object): def searchInsert(self, nums, target): for i in range(len(nums)): if nums[i]==target: return i else: nums.append(ta

2021-01-21 16:17:09 47

飞机大战素材和源码.zip

此资源是休闲小游戏《飞机大战》的源码与素材,主要使用了cocoscreator与vscode来开发,下载后直接解压,然后通过cocoscreator打开这个项目即可

2020-05-20

空空如也

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

TA关注的人

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