- 博客(92)
- 收藏
- 关注
原创 J.U.C包核心AQS(三):同步状态的获取与释放(独占/共享)
看过该系列第一篇文章的朋友相信还记得,对于同步状态的获取与释放,与我们自定义同步器时重写的tryAcquire()/tryRelease()(独占式)或者是tryAcquireShared()/tryReleaseShared()有关。因为 AQS 是基于模板方法设计模式设计的,线程获取锁时,由内部的同步器去调用 AQS 实现好的acquire()/acquireShared()方法,然后这些方...
2019-08-07 08:13:00
393
原创 J.U.C包核心AQS(二):同步队列
在该系列上一篇文章中:J.U.C包核心AQS(一):快速了解AQS我们了解到 AQS 有两个核心组成部分,一个是 int 型的同步状态 state,另一个就是一个内置的 FIFO 同步队列。上一篇文章简单的介绍了一下这个同步队列,本文将会具体的阐述这个同步队列的实现与等待线程排队的原理。...
2019-08-07 08:12:10
399
原创 J.U.C包核心AQS(一):快速了解AQS
AQS 是个啥?AQS,全称 AbstractQueuedSynchronizer,中文直译过来就是 “抽象的队列式的同步器”,它定义了多线程访问共享资源的同步器框架,J.U.C 包中很多同步类实现都依赖于它,比如我们常用的锁:ReentrantLock,又比如一些常用的并发工具类:CountDownLatch、Semaphore 等等。所以,很多人称 AQS 为 J.U.C 包的核心。那么要想...
2019-08-05 22:15:48
577
原创 lock.lock() 写在 try 代码块内部行吗?
熟悉 Java 并发的朋友,想必都会对 Lock 接口很熟悉,它是从 JDK1.5 以后提供给开发者的另一种线程同步的方式。下面是使用它的一个具体实现类:ReentrantLock 进行加锁解锁的一个小例子: Lock lock = new ReentrantLock(); lock.lock(); try { // access the resource protected by t...
2019-08-05 11:26:22
9285
12
原创 LCS 问题:最长公共子序列/最长公共子串
最长公共子序列求两个字符串的最长公共子序列(Longest Common Sequence,简称 LCS),比如:A = “abcdefg”B = “acbeg"那么这两个字符串的最长公共子序列便是:“aceg”。对于这种求取”最“值的问题,非常容易想到会使用动态规划来求解。使用动态规划解决问题其实并没有多难,它只需要你做好两件事即可:对状态做一个好的定义(即你的 dp 数组中的...
2019-07-26 12:28:28
488
原创 限流算法介绍
前言高并发的处理有三个比较常用的手段:缓存:比如将热点数据缓存在 Redis、MemCache 这种高性能的内存型数据库中,能有效地削减直接请求数据库的次数,加快响应速度,降低数据库的压力降级:服务降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。比如,在某宝双十一大促销的时候,用户是看不到一个月以前的历史订单的,这就是通过降级的手段,即暂时关闭了部分功能,来保证核心功...
2019-07-25 22:37:36
273
原创 Java 线程池详解(二):三个现成的线程池详解
前言原则上来讲,Java 的线程既是工作单元,也可以是执行机制。从 JDK1.5 开始,工作单元与执行机制可以被分离开来。其中,执行机制由 Executor 框架提供,而工作单元包括 Runnable 和 Callable(比较常规的两种声明线程的方法,可以通过传给 Thread 的构造函数来创建线程,并使用 Thread 实例的 start() 方法来启动线程,这种创建线程的方式,就是将工作单...
2019-07-22 19:37:12
587
原创 Java 四种权限修饰符所代表的可见性
本类中同一个包下其他类中子类中其他包下的所有类public可见可见可见可见protected可见可见可见不可见默认可见可见不可见不可见private可见不可见不可见不可见...
2019-07-22 11:24:35
575
原创 SSL/TLS 四次握手过程
SSL/TLS 背景介绍SSL(Secure Socket Layer 安全套接层)是基于 HTTPS 下的一个协议加密层,最初是由网景公司(Netscape)研发,后被 IETF(The Internet Engineering Task Force - 互联网工程任务组)标准化后写入(RFC:Request For Comments 请求注释),RFC 里包含了很多互联网技术的规范。起初是...
2019-07-21 19:22:49
1363
原创 判断一个数是否是素数(质数)
素数(质数)定义小学数学。。。这里复习一下。。。素数又称质数,一个大于1的自然数,除了 1 和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。0 和 1 既不是质数也不是合数,最小的质数是 2代码实现一、最暴力的实现:这里直接根据定义来判断一个数是否是素数 public boolean isPrime(int num) { if (num <= 3) r...
2019-07-21 13:50:05
510
原创 快速排序的三个优化思路
前言本文主要是介绍关于快速排序的三种优化思路,所以是基于读者已经掌握快速排序算法思想以及最基本的实现的前提,遂有关于快速排序原理方面,这里就不多赘述了。下面是快速排序最简单的实现版本,即每次选取待排序序列中最左侧的元素作为枢纽元。package SortPractice;import java.util.Random;public class QuickSortTest { /...
2019-07-18 11:15:33
1560
原创 Java 实现原子操作的方式
原子操作先来介绍一下啥是原子操作,原子(atomic)本意是 “不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为“不可被中断的一个或一系列操作”接下来,我们来看看实现原子操作的方式。 实现原子操作的方式 一、使用互斥(阻塞)同步实现原子操作最容易想到的方式便是互斥同步了,通过使用编程语言提供给我们的同步锁,比如 Java 的关键字 ...
2019-07-17 20:22:34
516
原创 ArrayList 的扩容机制
前言ArrayList 底层是基于数组实现的,不过得益于其扩容机制,它可以看作是一个动态的数组,弥补了数组长度是定长的缺陷。在往 ArrayList 里添加元素时,如果添加完元素之后,元素的总个数大于当前数组的容量,会执行扩容,这个扩容的过程可以归纳为以下两个步骤:确定新数组的容量将老数组内的元素拷贝到新数组中去确定新数组的容量这一步是本文重点,接下来我们一起来看一下。 ...
2019-07-08 09:56:37
715
原创 详解:重写 equals() 方法为何还要重写 hashCode() 方法?
前言这是一道常见的面试题,同时也是一个非常重要的 Java 基础知识点。在具体阐述标题内容之前,我们先来思考这样一个问题,何时需要重写这两个方法,也就是说在什么场景下,我们需要重写这两个方法?在绝大多数的情况下,重写这两个方法的是因为我们需要使用 HashSet 存储的元素类型是我们自己定义的对象类型,或者使用 HashMap 的时候,Key 的类型是我们自己定义的对象类型。public ...
2019-07-07 21:59:33
527
6
原创 Java 异常体系梳理
Java 异常体系ErrorError 表示系统致命的错误,程序无法处理,Error 类一般是指 JVM 相关的问题,如系统崩溃、虚拟机错误、内存空间不足等。常见的 Error 如 StackOverFlowError、OutOfMemoryError,对于这类错误,应用程序无法处理与恢复。ExceptionException 是 程序可以处理 的异常,可以被捕获可以被恢复,如上图所示,...
2019-07-05 17:46:08
199
原创 i++ 线程不安全示例详解
一个线程不安全的计数器package com.thread.xgb;public class UnsafeCounter { public int count = 0; public void add() { count++; } public int get() { return count; }}编写一个简单的测试用例来验证它在多线程环境下是线...
2019-07-04 13:17:59
3038
原创 synchronized 锁优化(一):自适应自旋锁、锁消除、锁粗化
本文中所提及的锁指的均是 JVM 提供的 synchronized.在并发编程中,synchronized 一直被称为重量级锁,但是随着 JDK1.6 对 synchronized 进行了各种优化之后,有些情况下它就并不那么重了。本文将介绍从 JDK1.6 开始引入的以下三种锁优化手段。自适应自旋锁(Adaptive Spining)锁消除(Lock Eliminate)锁粗化(Lock...
2019-07-03 21:22:14
2061
1
原创 synchronized 关键字的使用及其底层实现原理
synchronized 的使用Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized(关键字),而另一个是 JDK 实现的 ReentrantLock(类)。应该明确一个概念,那就是 synchronized 锁的都是对象,而非代码!Java 中的每一个对象都可以作为锁。synchronized 有四种使用方式。这四种使用方式又可以...
2019-07-03 17:38:22
986
原创 synchronized 锁优化(二):锁的状态及锁膨胀
本文中所提及的锁指的均是 JVM 提供的 synchronized.在并发编程中,synchronized 一直被称为重量级锁,但是随着 JDK1.6 对 synchronized 进行了各种优化之后,有些情况下它就并不那么重了。本文将介绍从 JDK1.6 开始引入的新的锁状态的概念以及锁升级的过程(即所谓的锁膨胀)。 Java 对象头在正式介绍之前,先要明确一下对象头这个概念。...
2019-07-03 10:57:48
1424
2
原创 volatile 关键字的底层实现原理
参考书籍:《Java 并发编程的艺术》 - 方腾飞 魏鹏 程晓明著在并发编程中,synchronized 和 volatile 这两个关键字都扮演着重要的角色,volatile 是轻量级的 synchronized,它在多处理器开发中保证了共享变量的 “可见性”。那么什么是 “可见性” 呢?可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值如果 volatile...
2019-07-02 21:26:01
715
原创 线程的六种状态及其转换
线程的六种状态介绍线程的几种状态可以在 Thread 类的源码中看到,它位于名叫 State 的枚举中。如下所示,一共有六种。1. 新建(New):线程创建后尚未启动的状态(即创建后还未调用 start() 方法)。2. 可运行(Runnable):可能正在运行,也可能正在等待 CPU 时间片,包含了操作系统线程状态中的 Running 和 Ready。3. 阻塞(Blocked)...
2019-07-02 17:00:10
605
原创 提取图片色彩比例(Java 代码实现)
背景介绍之前应一个中科院生态环境研究院的朋友邀请,为其所在团队开发一款调查问卷形式的小程序,其中有一个主要功能是需要用户上传所处位置东南西北四个方向的照片,然后在服务端对这四张图片进行解析,提取出图片中人眼所见绿色所占整张图片的比例。打个比方,如下这张图片人眼所见的话,绿色占比大概在 30% ~ 40% ,我服务端的应用程序需要把这个绿视率计算出来,并保存在数据库里。碍于没有图像处理的相...
2019-07-02 14:42:12
6140
7
原创 Java 四种引用类型
在 JDK 1.2 以前,Java 中的引用的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。这种定义很纯粹,但是太过于狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些 “食之无味,弃之可惜” 的对象就显得无能为力。在 JDK 1.2 之后,Java 对引用的概念进行了扩充,将引用扩充为如下四种...
2019-07-01 16:47:56
190
原创 JVM几种常见的垃圾收集器总结
前言在介绍垃圾收集器之前,首先介绍以下这几个概念1. Stop-the-world它是指 JVM 由于要执行 GC 而停止了应用程序的执行,并且这种情形会在任何一种 GC 算法中发生。当 Stop-the-world 发生时,除了 GC 的线程以外,其他的线程均处于等待的状态,直到 GC 任务完成。实际上,很多 GC 优化都是通过减少 Stop-the-world 的时间来提高程序的性能。...
2019-07-01 15:27:46
9063
1
原创 JVM垃圾回收与内存分配策略
Java 技术体系中所提倡的自动内存管理最终可以归结为自动化地解决了两个问题:给对象分配内存回收分配给对象的内存堆区内存结构图(JDK1.8 之后移除了永久代,GC 只需要对堆区的新生代和老年代负责)其中,Eden 区(就是伊甸园的意思,所有对象的起源,在后面介绍分配策略的时候你会更加明白为什么这么命名),From 区和 To 区是两块 Survivor 区(幸存者空间)。相关性能...
2019-07-01 10:03:56
256
原创 JVM垃圾收集算法总结
JVM 所采用的垃圾收集算法主要有如下三种:标记 - 清除算法标记 - 整理算法复制算法我们来逐一看一下。 一、标记 - 清除算法如同它的名字一样,算法分为 “标记” 和 “清除“ 两个阶段:标记阶段:标记出所有需要回收的对象。(标记方法为 GC Roots可达性分析算法)清除阶段:统一回收刚刚所有被标记的对象。图示如下:这种算法主要有两个缺点:标记和...
2019-07-01 08:24:27
139
原创 判断对象是否凉了的两个算法
判断一个对象是否为垃圾的算法主要有如下这两种:引用计数算法可达性分析算法下面我们来分别看一下。 引用计数算法为对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。优点:实现简单执行效率高,对程序的执行影响较小引用计数算法在大部分情况下它都是一个不错的算法,也有一些比较著名的应用案例,比如使用 Act...
2019-06-30 16:28:46
156
原创 Java虚拟机运行时数据区域
运行时数据区域整体概览下图为 JDK1.6 版本的 Java 虚拟机运行时数据区域。关于新版本的改动:JDK1.7 将字符串常量池从运行时常量池挪到了堆中JDK1.8 对比 JDK 1.7 最大的改动就是使用元空间替代了永久代(即方法区)的实现,并且元空间被挪到了本地内存当中。原来方法区中存放的已被加载的类信息置于元空间中,而原来方法区中存放的常量池被放入堆中。如下图所示本文主要...
2019-06-29 14:30:44
338
原创 Java虚拟机的结构梳理
可以归纳为如下四个部分: 类加载器(Class Loader):把描述类的数据从 Class 文件加载到内存,除了启动类加载器是 Java 虚拟机的一部分以外,其他的类加载器是被放到 Java 虚拟机外部去实现的,以便让应用程序自己决定如何去获取所需要的类。运行时数据区域(Runtime Data Area):Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同...
2019-06-29 10:09:27
187
原创 loadClass()和forName()的区别
类加载的方式主要有两种:隐式加载:使用 new + 构造方法时,隐式的调用类加载器,加载对应的类到 JVM 中,是最常见的类加载方式。显式加载:使用 loadClass()、forName() 等方法显式的加载需要的类,对于显式加载这种类加载方式来讲,当我们获取到了 Class 对象后,需要调用 Class 对象的 newInstance() 方法来生成对象的实例。两种类加载方式的区别...
2019-06-28 21:53:03
7577
3
原创 虚拟机类加载机制总结
简介虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。 类的生命周期类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括如下 7 个阶段:加载(Loading)验证(Verification)准备(Preparation)解析(Resolut...
2019-06-28 19:47:27
415
原创 一文搞懂双亲委派模型
类加载器虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。从 Java 虚拟机的角度来讲,只存在以下两种不同的类加载器:启动类加载器(Bootstrap ClassLoader),使用 C++ 实现,是虚拟机自身的一部分所有其它类的加载...
2019-06-28 14:42:07
21829
6
原创 实现一个自己的ClassLoader
ClassLoader 简介 ClassLoader 在 Java 中有着非常重要的作用,它主要工作在 Class 装载的加载阶段。其主要作用是从系统外部获得 Class 二进制数据流。它是 Java 的核心组件,所有的 Class 都是由 ClassLoader 加载的,ClassLoader 负责通过将 Class 文件里的二进制数据流装载进系统,然后交给 Java 虚拟机进...
2019-06-28 10:39:11
829
原创 联合索引的最左前缀匹配原则介绍
联合索引 所谓的联合索引就是指,由两个或以上的字段共同构成一个索引。本文测试用例的数据表结构如下,一张简简单单的学生信息表 tb_student,仅包含四个字段(student_id、student_name、student_age、student_addr)那比如说,我们现在的业务需求经常要通过学生的年龄(student_age)和学生的家庭住址(student_addr)来...
2019-06-27 18:29:25
16080
11
原创 SQL视图总结
什么是视图?视图是从一个或多个表导出的虚拟的表,其内容由查询定义。具有普通表的结构,但是不实现数据存储,所以用户不需要担心视图会充满磁盘空间。而且,对视图的操作和对普通表的操作一样。创建视图的例子:假设我这有一张用户信息表,如下所示我现在想对用户提供一个用户 id 在 10 以下的包含用户姓名、头像地址、性别这三个属性的视图,那么执行以下语句。CREATE VIEW person_v...
2019-06-27 13:54:09
711
原创 实体首部字段Content-Type小结
Content-Type 简介Content-Type 又称 MIME 类型,在互联网中有成百上千中不同的数据类型,HTTP 在传输数据对象时会为他们打上称为 MIME 的数据格式标签,用于区分数据类型。最初 MIME 是用于电子邮件系统的,后来 HTTP 也采用了这一方案。我们用 Chrome 的开发者模式以访问百度为例,简单看看 Response 的几种 Content-Type 类型。...
2019-06-25 19:21:18
265
原创 稳定排序的代码你写对了吗?
前言所谓的稳定排序是指原来相等的两个元素前后相对位置在排序后依然不变。未曾了解过这方面的朋友可以看一看我下面这篇文章。 几种排序算法的稳定性分析常见的能够保证稳定性的排序算法有冒泡排序插入排序归并排序注意,我说的是能够保证稳定性,而非是一定稳定,这与你对算法的实现息息相关,本文就这三种可以保证稳定性的算法中较为复杂的归并排序进行举例,来阐述这篇文章的主要思想。 不...
2019-06-25 13:56:47
436
原创 几种排序算法的稳定性分析
稳定指的是什么? 稳定排序是指原来相等的两个元素前后相对位置在排序后依然不变。 为什么要对排序算法提出稳定性的要求? 简单的举个小例子:比如我们班一次期末考试,分高的在前面,对于分数相同的学生的排名需要借助上次考试结果,上次分数高的在前面,那么这个时候就要使用稳定排序。又比如,我们需要对学生先进行年龄排名,然后再根据身高排名,身高相同的,要求年龄大的在前...
2019-06-25 12:07:02
10238
1
原创 减少上下文切换的方式
参考书籍:《Java 并发编程的艺术》— 方腾飞 魏鹏 程晓明 著 什么是上下文切换 即使是单核 CPU 也是支持多线程技术的,CPU 通过给每个线程分配一定量的 CPU 时间片来实现这个机制。时间片是 CPU 分配给各个线程的时间,因为时间片非常短,所以 CPU 通过不停地切换线程执行,让我们感觉多个线程是同时执行,时间片一般是几十毫秒。CPU 通过时间片分配算法来...
2019-06-24 18:41:39
1023
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人