自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

卓立的博客

Java技术分享

原创 Java编程拾遗『AQS』

上篇文章讲了Java中显式锁Lock和ReadWriteLock的概念及简单使用示例,本篇文章重点来看一下Java中显式锁的底层实现。在看这部分代码时,我任务比较好理解的方式是带着问题去看源码。对于显式锁,我们可能会有以下问题:问题1:显式锁底层是基于CAS实现,细节是怎样的? 问题2:显式锁跟synchronized类似,无法获取锁时,会阻塞当前线程,如何实现阻塞的? 问题3:显式锁提供...

2019-08-16 07:19:59 80

原创 理解Https

之前的文章讲golang webSocket编程的文章中提到过Http协议的概念,通过之前的了解我们也知道Http协议其实就是基于传输层的TCP协议和网络层的IP协议实现的一个协议,所以他拥有TCP/IP的所有特性。也正是因为它使用TCP/IP协议,导致它会有以下问题:通信使用明文,通信内容有可能会被窃听 不验证通信方的身份,有可能遭遇伪装 通信内容可能遭到篡改1. HTTP存在的风险...

2019-08-16 07:10:32 73

原创 了解Cookie、Session和Token

在Web刚兴起的阶段,Web服务都是静态服务,一般处理前端请求,只需要将相应的html、图片等文件传送到前端即可,这个时候,对于同一个请求,每个用户看到的内容都是完全一样的,服务器也没必要针对不同用户做不同的处理。Http协议最开始就是定义服务器和客户端传送超文本文件的协议,从起源上看,Http协议就是无状态的。但是随着交互式Web应用的兴起,之前无状态的Http协议就不能满足了。比如购物、论...

2019-08-15 07:27:43 53

原创 redis实现分布式锁

分布式锁一般有三种实现方式:Zookeeper Redis 数据库排他锁从可靠性和实现的复杂度讲,上面三种方式在可靠性上逐渐降低,在实现复杂度上也是逐渐降低的。在实际使用中,通过redis实现分布式锁是一种比较常见的方式,但是在使用redis实现分布式锁时,有些不正确的实现往往会导致死锁,错误等问题。本篇文章就来讲解一下redis实现分布式锁的常见方式,及redis分布式锁的正确打开方式...

2019-08-15 07:26:12 115

原创 Spring源码解读『AOP』

之前的文章我们介绍了Spring IOC的相关概念及相应的底层源码实现,本篇文章我们来看一下Spring的另一重要特性AOP的相关细节。1. AOP示例1.1 Bean interfacepackage com.zhuoli.service.spring.explore.aop.bean;public interface AopBean { void method1(); void method2();}1.2 Bean interface实现packag

2020-07-10 07:45:55 32

原创 Spring源码解读『通过配置类启动spring容器』

之前的介绍中,Spring容器都是通过xml配置文件启动的,在实际开发中,xml配置的使用是逐渐减少的,一般在开发中更建议使用Java Config。本篇文章我们就来看一下Spring容器如何通过配置类启动的。Spring提供了AnnotationConfigApplicationContext类,实现通过Java Config配置类来启动Spring容器。1. 示例1.1 定义Beanpublic class TestBeanA { private String testName

2020-07-10 07:45:11 27

原创 Spring源码解读『占位符@Value(“${…}”)替换』

上篇文章介绍了xml配置文件中占位符${…}的解析过程,本片文章我们来继续介绍Spring中另一种占位符@Value(“${…}”),这种占位符一般出现在Java Config中,如下:@Configurationpublic class MyConfiguration { @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String userName;

2020-07-10 07:44:22 302

原创 Spring源码解读『占位符${…}替换』

在使用Spring时,对于一些比较固定的参数,我们一般会采用配置的方式,将这些参数配置在.properties配置文件中,然后在Bean初始化过程中替换为配置文件中配置的真实值。在Spring中,这种典型的的使用会存在以下两种方式:在xml配置中,通过${…}:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:

2020-07-10 07:43:37 84

原创 Spring源码解读『@Configuration配置类』

上篇文章我们介绍了通过xml配置文件来解析Bean配置的过程,本篇文章我们来看另一种解析Bean配置的方式,@Configuration配置类。在Spring应用中,为了使用@Configuration配置类,如果使用xml启动ApplicationContext,我们一般会在xml配置文件中加上如下一行配置:<context:component-scan base-package="com.zhuoli.service.spring.explore.config"/>以告诉Sprin

2020-07-10 07:42:04 47

原创 Spring源码解读『配置文件解析』

之前的文章详细介绍了Bean的实例化和初始化的过程,但其实Bean能实例化、初始化的前提是Spring容器在启动时,间配置文件(配置类)中的配置加载成BeanDefinition,这一点我们再之前的文章Spring源码解读『IOC容器1-自定义实现IOC容器』一文中看得比较清楚。关于Spring对配置文件(配置类)的处理,我们还没有介绍,本篇文章我们就来介绍一下Spring容器启动时是如何加载xml配置文件并加载成BeanDefinition的,在下篇文章来介绍@Configuration配置类。首先来看一

2020-07-10 07:40:06 26

原创 Spring源码解读『Spring Bean循环依赖』

由于Spring的IOC特性,Bean都是由Spring容器生成的,那么如果Bean是单例的,存在两个Bean,分别为beanA、beanB,beanA依赖beanB,同时beanB也依赖beanA,那么可以想象假如容器不做特殊处理的话,就会发生循环依赖,产生死锁,Bean构造就进行不下去了。但是我们在使用时,其实并没有关注循环依赖的问题,Spring是可以解决这种循环依赖的情况的,本篇文章我们来看一下Spring是如何解决循环依赖的。1. Spring循环依赖示例首先定义两个Bean,BeanA和

2020-06-30 08:37:07 38

原创 Spring源码解读『Bean扩展接口』

上篇文章我们介绍了Spring Bean的初始化流程,在最后我们提到在通过populateBean方法调用后,调用了initializeBean方法,实现了一些列例如BeanNameAware、BeanPostProcessor等扩展接口的调用,本篇文章我们就来看一下Spring提供给开发者的一些扩展接口。Spring框架运用了非常多的设计模式,从整体上看,它的设计严格遵循了OCP——开闭原则:对修改关闭,外部无法修改Spring整个运作的流程 对扩展开放,可以通过继承、实现Spring提供的众多

2020-06-30 08:36:29 25

原创 Spring源码解读『IOC容器3-Bean初始化』

上篇文章我们介绍了Spring源码阅读的入口,分析了通过xml配置文件到Spring Bean初始化出来的流程。在上篇文章中,我们讲到,所有非懒加载的bean都是在finishBeanFactoryInitialization方法中完成实例化和初始化。由于该方法是整个Bean加载流程的核心方法,并且介绍起来篇幅较长,所以该方法单独在本篇文章介绍。在阅读源码之前,我们可以简单想象一下该方法的实现内容。在该方法执行之前,所有的Bean配置(通过xml配置文件或者配置类)都已经转变层BeanDefinition并

2020-06-30 08:35:47 39

原创 Spring源码解读『IOC容器2-Bean加载过程』

上篇文章,我们自定义实现了一个简单地IOC容器。本篇文章我们来介绍一下Spring IOC容器的实现。1. 准备工作为了学习Spring的源码实现,我们需要准备Spring的源码环境,这时我们一般可以有以下两种选择:1.1 下载spring-framework git项目将spring-framework git项目下载到本地git clone https://github.com/spring-projects/spring-framework.git将源码导入到Idea中这

2020-06-30 08:34:59 34

原创 Spring源码解读『IOC容器1-自定义实现IOC容器』

上篇文章介绍了Spring的相关基础概念,我们了解到Spring Framework提供的两个基础功能就是IOC和AOP。关于IOC容器我们分为两篇文章来介绍,本篇文章会介绍IOC容器的基础概念,并自定义实现一个基础的IOC容器,帮助我们后续更好的解读IOC源码。AOP会在之后的文章中介绍。1. IOC容器基本概念IOC(Inversion Of Control)也叫控制反转,这个概念经常会伴随另一个概念DI(Dependence Injection)依赖注入出现。直白的讲就是,Java中一个对象依

2020-06-30 08:31:52 47

原创 Spring源码解读『基本概念』

Spring作为一个优秀的开源框架,作为一名服务端开发人员,在工作中必然是每天都要接触的,相信每个人也都能熟练地使用Spring来完成日常工作。毫不夸张的讲,Spring很大程度上改变了Java开发的方式。但是在工作中,我发现很多数人对Spring的了解都停留在表面,很少去深究Spring这一优秀框架底层的原理。结合我自身的体会而言,在刚开始接触这个框架的时候,仅仅是生硬地去记它的一些使用特性,一旦遇到一些“非常规”问题,就搞不定了。随着使用的深入,疑惑的问题越来越多(比如框架给我们带来什么好处?Sprin

2020-06-30 08:31:08 44

原创 使用Netty实现RPC

Netty作为一个异步事件驱动的网络应用框架,可以用于快速开发可维护的高性能服务器和客户端。国内著名的RPC框架Dubbo底层使用的是Netty作为网络通信的。本篇文章我们来探索一下RPC框架的本质以及使用Netty来实现一个简单地RPC框架。1. RPC是什么RPC(Remote Procedure Call),翻译成中文就是远程过程调用。远程过程就是相对于本地方法而言的,是运行在某个远程的地方而不是本地。通过RPC可以实现像本地函数调用一样调用远程服务,是一种进程间的通信方式。RPC调用的本质可

2020-06-30 08:30:15 50

原创 使用Netty实现HTTPS

之前的文章理解Https中,介绍了HTTP到HTTPS的演进过程,我们也可以得到一个结论:HTTPS = HTTP + 加密 + 身份认证 + 报文正确性保障。其实也就是在HTTP层和TCP层之间新增一个步骤,通过证书交换通信秘钥并验证客户端服务端身份的合法性(SSL)。所以为了实现HTTPS,必须支持SSL。为了支持SSL,Java提供了 javax.net.ssl 包,它的SSLContext 和SSLEngine类使得解密和加密相当简单和高效。Netty提供了基于SSLEngine的实现OpenS

2020-06-30 08:29:27 105

原创 Netty基础组件

之前的文章Netty基础篇:Netty是什么?介绍了传统IO编程存在的问题,及Java NIO编程在解决IO编程的问题中的局限性,由此引出IO编程问题的理想解决方案——Netty。在上篇文章中简单展示了Netty的基本使用,本篇文章通过一个Netty服务端的demo来了解一下Netty的基本组件。1. Netty服务端public class EchoServer { private final int port; public EchoServer(int port) {

2020-06-30 08:27:56 29

原创 Java编程拾遗『JVM垃圾回收』

垃圾收集(Garbage Collection)通常被称为GC,大部分人都把这项技术当作Java语言的伴生产物。事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp语言是第一门真正使用内存动态分配和垃圾收集技术的语言。经过半个世纪的发展,内存动态分配与内存回收技术已经相当成熟,一切看起来都进入“自动化”时代,那么为什么我们还要去了解GC和内存分配呢?原因很简单:当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”技术实施必要的监控和调

2020-06-30 08:26:36 40

原创 Nginx + Lua开发

之前Nginx那篇文章讲过,我希望通过Nginx做一个测试环境,目标其实很简单,其实就是使用Nginx做反响代理服务器,绕过现在的鉴权系统,将前端请求转发到相应人员的“开发机”上去,其实在过程中遇到几个比较棘手的问题,如下:如何确定相应的前端请求到后端服务映射,即区别前端请求,将需求A的前端请求转发需求A的机器上而不会转到需求B的开发机上 后端服务会对请求体进行SHA-1数据加密校验,将请求...

2020-01-07 07:47:49 271

原创 Java编程拾遗『JVM内存区域』

作为一名Java开发人员,JVM是我们每天都会打交道的对象。但是由于JVM处于知识体系的底层,同时工作中有可能接触的机会不是很多,导致很多人都对JVM相关的知识一知半解。一般只会在面试的时候,才来准备这部分内容。但JVM是为了让我们更好的理解Java,更深入了解我们每天开发程序的执行机制。所以从本篇文章开始,我们来介绍以下JVM相关的知识。大致规划一下应该会包括 以下内容:JVM内存区域、垃圾...

2020-01-07 07:43:15 93

原创 Java编程拾遗『Java ClassLoaser工作机制』

ClassLoader顾名思义就是类加载器,负责将类的.class文件中的二进制数据加载到JVM中,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构(类的方法代码,变量名,方法名,访问权限,返回值等)。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。类加...

2020-01-07 07:41:48 47

原创 Java编程拾遗『ThreadLocal』

本篇文章,我们来介绍一下,Java多线程编程中一个比较常用的工具,线程本地变量——ThreadLocal。ThreadLocal简单的来讲,就是每个线程都有同一个成员变量的独有拷贝。由于每个线程都有成员变量独立的拷贝,所以不存在多线程访问同一成员变量的问题,也就解决了线程安全问题。之前我们介绍的锁,是解决线程安全问题的一个途径,那么本篇文章介绍的线程本地变量是另一种解决线程安全问题的思想,就是通过...

2020-01-07 07:39:31 52

原创 Java编程拾遗『线程协作工具』

在之前的文章Java编程拾遗『线程协作』中,介绍了一些线程协作的场景,并做了简单的代码实现,比如上文中的MyLatch、AssemblePoint、MySemaphore等。其实上篇文章介绍的线程协作场景,在Java API中都有响应实现。本篇文章就来介绍一下,Java API中提供的一些线程协作工具及使用场景。本篇文章会介绍以下几种协作工具:CountDownLatch CyclicBar...

2020-01-07 07:38:05 46

原创 Java编程拾遗『线程池』

在之前的文章中,我们已经讲了很多Java线程的使用以及Java并发编程的原理,本篇文章,我们来重点看一下Java并发编程中一个比较常用的工具——线程池的使用以及源码实现,这也是Java面试的基本问题。在使用线程池之前,我们可以尝试考虑这样一个问题,如果没有线程池,我们是怎样实现多线程编程的以及实现方式有哪些问题?首先,如果没有线程池,我们一般会直接通过new Thread()构造出多个线程,然...

2020-01-07 07:36:59 66

原创 Java编程拾遗『并发容器——并发队列』

本篇文章,来探讨一下Java并发包中的各种队列。Java并发包提供了丰富的队列类,可以简单分为:无锁非阻塞并发队列:ConcurrentLinkedQueue和ConcurrentLinkedDeque 普通阻塞队列:基于数组的ArrayBlockingQueue,基于链表的LinkedBlockingQueue和LinkedBlockingDeque 优先级阻塞队列:PriorityBl...

2020-01-07 07:34:15 34

原创 Java编程拾遗『并发容器——ConcurrentSkipListSet和ConcurrentSkipListMap』

由于水平有限,ConcurrentSkipListSet和ConcurrentSkipListMap的实现又比较复杂,所以并没有去通读源码。下文的内容来自《Java编程的逻辑》,简单讲了ConcurrentSkipListMap基于跳跃表实现的思想,有兴趣的小伙伴也可以去读一下源码。之前的文章介绍了ConcurrentHashMap,也讲到ConcurrentHashMap不能排序,容器类中可...

2020-01-07 07:32:34 38

原创 Java编程拾遗『并发容器——ConcurrentHashMap』

在之前的文章中已经介绍过的哈希表数据结构有HashMap、TreeMap、LinkedHashMap、HashTable以及Collections类生成的各种同步Hash容器。但是我们也了解到,HashMap是非线程安全的,在多线程环境下会出现数据安全性问题,比如多线程同时rehash过程中产生的死循环(Java7)及元素丢失问题。HashTable和Collections类生成的同步容器倒是可以...

2020-01-05 10:42:43 48

转载 秒懂 QPS、TPS、PV、UV、GMV、IP、RPS

QPS、TPS、PV、UV、GMV、IP、RPS等各种名词,外行看起来很牛X,实际上对程序员来说都是必懂知识点。下面我来一一解释一下。1. QPSQueries Per Second,每秒查询数。每秒能够响应的查询次数。QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。每秒的响应请求数,也即是最大吞吐能力。...

2020-01-05 10:39:13 23

转载 一份非常完整的MySQL规范

1. 数据库命令规范所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份表必须以bak_为前缀并以日期(时间戳)为后缀 所有存储相同数据的列名和列类型必须一致(一般作为关联列,如...

2020-01-05 10:38:00 30

原创 Java编程拾遗『并发容器——CopyOnWrite』

从本片文章开始我们来介绍并发容器类,之前的文章介绍过普通容器类,比如ArrayList、LinkedList等。但是这些容器都有个问题,就是非线程安全,多线程并发写,会存在线程安全问题,所以Java提供了并发容器类来解决普通容器类的线程安全问题。本篇文章我们先来看一种解决容器类线程安全的思想——CopyOnWrite(写时复制)。1. 同步容器在讲CopyOnWrite并发容器之前,先来介...

2020-01-05 10:36:47 33

转载 秒懂 QPS、TPS、PV、UV、GMV、IP、RPS

原文链接:http://unvcn.com/post/50.htmlQPS、TPS、PV、UV、GMV、IP、RPS等各种名词,外行看起来很牛X,实际上对程序员来说都是必懂知识点。下面我来一一解释一下。1. QPSQueries Per Second,每秒查询数。每秒能够响应的查询次数。QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的...

2019-08-16 07:24:26 254

转载 一份非常完整的MySQL规范

原文链接:https://www.cnblogs.com/duaimili/p/10277515.html1. 数据库命令规范所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备...

2019-08-16 07:22:52 35

原创 Java编程拾遗『并发容器——CopyOnWrite』

CopyOnWrite

2019-08-16 07:21:37 51

原创 Java编程拾遗『显式锁』

在之前讲线程同步时,介绍了synchronized的锁的使用及底层原理,也介绍了synchronized锁的一些使用局限,本篇文章来介绍一下Java中提供的另一种线程同步机制——显式锁。Java并发包中的显式锁接口和类位于包java.util.concurrent.locks下,主要接口和类有:锁接口Lock,主要实现类是ReentrantLock 读写锁接口ReadWriteLock,主要...

2019-08-16 07:17:57 41

原创 Java编程拾遗『原子变量』

本篇文章我们来讲java.util.concurrent包下的原子变量,原子变量的引入主要是为了解决普通变量(int、Integer、Long等)修改操作不是原子的,进而导致必须使用同步机制才能保证安全更新的问题。举个例子:public class Counter { private int count; public void incr(){ count ...

2019-08-16 07:16:12 33

原创 Java编程拾遗『线程中断』

之前的文章,我们已经介绍了线程的概念、使用、同步及线程协作,本篇文章来重点讲一下Java中如何取消或关闭一个线程。1. 线程取消/关闭的场景我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种情况,比如说:很多线程的运行模式是死循环,比如在生产者/消费者模式中,消费者主体就是一个死循环,它不停的从队...

2019-08-16 07:14:25 28

原创 Java编程拾遗『线程协作』

之前用了两篇文章介绍了多个线程竞争资源的解决方案synchronized,但其实多个线程之间除了竞争资源之外,还有相互协作。比如:生产者/消费者模式:这是一种常见的协作模式,生产者线程和消费者线程通过共享队列进行协作,生产者将数据或任务放到队列上,而消费者从队列上取数据或任务,如果队列长度有限,在队列满的时候,生产者需要等待,而在队列为空的时候,消费者需要等待。 同时开始:类似运动员比赛,在...

2019-08-16 07:13:16 34

原创 Redisson实现Redis分布式锁

在上篇文章redis实现分布式锁中,讲了通过redis实现分布式锁的正确方式,并在文章最后讲到,文章中的实现方式存在单点问题,并提到一种基于分布式环境的分布式锁——Redlock。本文就讲解一下Redlock的一些概念和实现。1. RedissonRedisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的J...

2019-08-15 07:33:45 82

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