注:本文中的部分内容摘抄自他人博客,如有侵权,请联系我,侵删~ 本篇博客主要讲述 synchronized 关键字的实现原理以及 JDK 1.6 后对 synchronized 的种种优化。synchronized 的使用不再赘述。 博主目前依旧存在的疑惑 请在阅读完此篇博客之后,帮助博主回答这三个问题: 多线程争夺 Monitor 的具体过程是怎样的?是根据 ObjectMonitor 中的 _count 值判断当前 Monitor 是否被锁定吗? JVM 如果检测到在单线程环境下执行同步代码(StringBuffer),是会进行锁消除呢,还是会使用偏向锁? 对于偏向锁的撤销过程及膨胀过程,博主只是在一些博客的基础上给出了自己的理解!不权威,建议阅读源码,博主对这部分知识的讲解持怀疑态度,如果在阅读的过程中发现博主对偏向锁的撤销与膨胀理解有误,请指出,感激不尽~(网上基本上没有从源码角度分析的,对于偏向锁撤销与升级的详细过程也是众说纷纭) 引言 我们先来看一份代码: 继续阅读 >>


董恒毅 18/04/27 11:38:27
注:感谢 美团点评技术团队 的分享~~,博客部分内容摘抄自其中。侵删! 今天我们来探究一下 HashMap 的内部实现机制。 明确 JDK 1.8 中的 HashMap 使用数组 + 链表 + 红黑树的结构进行实现。 HashMap 的底层思想主要是哈希表,我们来看看 Java 的设计者们是怎么使用数组 + 链表 + 红黑树设计出 HashMap 的。 HashMap的基本属性 既然是用哈希表进行实现,那么基本的数据结构就是数组了,HashMap 部分源码如下: public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { transient Node<K,V>[] table; // HashMap 底层数据结构(Node 数组) transient int size; 继续阅读 >>


董恒毅 18/04/20 21:55:40
源码地址:XiyouLinux Group 图书借阅平台 项目地址中包含了一份README,因此对于项目的介绍省去部分内容。这篇博客,主要讲述项目中各个模块的实现细节。 项目概述及成果 首先将本项目使用到技术罗列出来: 使用Spring + Spring MVC进行后台开发 使用Bootstrap和jQuery框架进行前端开发 使用自定义注解与自定义的JdbcRowMapper简化JdbcTemplate对数据库的操作 使用腾讯云的对象存储服务进行图书照片的远程存储 使用MD5加密算法对用户密码在后台进行加密存储 使用过滤器进行一个会话中的身份校验 手动从Spring容器中获取bean 数据库设计中的诸多细节… … 由于前端开发是由团队中的其他人在负责,在加上博主对前端这块并不了解,因此本篇博客并不讨论有关第二点技术实现上的细节。 本项目如README中所述,在后期还有许多需要进行优化的地方。如果你对本项目感兴趣,不妨在GitHub中将 继续阅读 >>


董恒毅 18/03/13 00:22:30
注:本篇博客大部分内容截选自阮一峰老师的DNS 原理入门一文。其中少部分内容是博主自己的理解。 什么是DNS 我们知道,网络本身只能理解数字形式的地址,也就是IP地址。但是直观的IP地址毫无规律,很难让人记住,并且如果使用IP地址浏览一个公司的主页,意味着这家公司一旦将主页移动到了另一台机器上,且该机器具有不同的IP地址,那么必须将该机器的IP地址通知给每一个人。因此人们引入了类似于www.baidu.com这样的域名。而要将域名转换为对应的IP地址,就需要DNS服务器(Domain Name System)。 在早期的ARPANET时代,只有一个简单的hosts.txt文件,它列出了所有的计算机名字和其对应的IP地址。每天晚上,所有的主机都从一个维护此文件的站点将该文件取回,然后在本地进行更新。对于一个拥有几百台大型分时机器的网络而言,这种方法工作的相当好。 然而当几百万台PC连接到互联网以后,问题就出现了。首先这个文件会变的非常大,并且主机名冲突的现象将会频繁发生。为了解决这些问题,DNS服 继续阅读 >>


董恒毅 18/03/05 18:01:22
源码地址:多线程爬虫–抓取淘宝商品详情页URL 项目地址中包含了一份README,因此对于项目的介绍省去部分内容。这篇博客,主要讲述项目的构建思路以及实现细节。 项目概述及成果 首先将本项目使用到技术罗列出来: MySQL数据库进行数据持久化及对宕机情况的发生做简单的处理 Redis数据库做IP代理池及部分已抓取任务的缓存 自制IP代理池 使用多线程执行任务(同步块,读写锁,等待与通知机制,线程优先级) HttpClient与Jsoup的使用 序列化与反序列化 布隆过滤器 之后会对其中使用到的技术进行详细的解释。 本项目如README中所述,还有许多不完善的地方,但IP代理池与任务抓取线程之间的调度与协作基本已无问题。也就是说,在此项目的框架上,如果你想修改其中代码用作其他抓取任务,也是完全可以的。我抓取到的数据所保存的源文件也放在GitHub的README上供大家免费浏览与下载(近90000的商品ID)。 整体思路 首 继续阅读 >>


董恒毅 18/03/02 22:35:30
由于我将继承与多态的讲解分成了三篇博客,所以在这篇博客给出三篇博客总的链接,阅读顺序由第一篇至第三篇就可以。 第一篇:主要讲解分派:JVM–详解虚拟机字节码执行引擎之静态链接、动态链接与分派 第二篇:主要讲解invokevirtual指令:JVM–从JVM层面深入解析对象实例化、多态性实现机制 第三篇:主要讲解继承与方法表: JVM–再谈继承与多态 相信这三篇博客会给你带来惊喜~~~ 作者:championhengyi 发表于 2018/01/12 14:53:43 原文链接 https://blog.csdn.net/championhengyi/article/details/79044061 阅读:334 继续阅读 >>


董恒毅 18/01/12 14:53:43
此文试图从JVM层面深刻剖析Java中的继承与多态,知识面覆盖class字节码文件,对象的内存布局,JVM的内存区域、分派,方法表等相关知识,内容整合于大量博客,知乎,书籍,并加上博主自己的理解,相信看完会对你大有裨益! 即使博主在JVM专栏已经有两篇博客对多态的实现机制进行了分析,但是今天在分析了一波继承的原理之后,发觉之前对于多态的讲述还不完整,在查阅的相关资料之后,决定在这一篇博客真正的将继承与多态讲透彻! 注:本篇博客有部分内容摘抄自:从JVM角度看Java多态。表示感谢~ 先来看一份代码: class Parent { protected int age; public Parent() { age = 40; } void eat() { System.out.println("父亲在吃饭"); } } class Child extends Parent { protected int a 继续阅读 >>


董恒毅 18/01/10 16:14:59
之前一直觉得对于字节码的执行过程,对象的实例化过程,多态的实现机制没有进行深刻的探讨,只是进行了简单的总结,一直也苦于没有找到恰当的例子,所幸今天看到一前辈的博客,对其进行钻研之后,终于解决了这个历史遗留问题。 首先贴出前辈的原文链接,并且这篇博客会引用其中的一些内容:Java重写方法与初始化的隐患 问题的还原 先来看一份代码: public class SuperClass { private int mSuperX; public SuperClass() { setX(99); } public void setX(int x) { mSuperX = x; } } public class SubClass extends SuperClass { private int mSubX = 1; public SubClass() {} @Override publ 继续阅读 >>


董恒毅 18/01/08 18:24:57
JVM开发团队一直在努力,缩小Java与C/C++语言在运行效率上的差距。 本篇博客,我们来谈一谈JVM(HotSpot)为了提高Java程序的运行效率,都实现了哪些激动人心的技术~ JIT编译器的引入 首先我们这篇文章中所说的编译器都是指JVM的组成部分之一—即时编译器(JIT),与生成Java字节码的javac编译器要区分开来。 你也许想说,为什么要引进JIT编译器?很好的问题。 我们知道,javac将程序源代码编译,转换成Java字节码,解释器对字节码进行解释执行。而虚拟机传统的解释器,就是要将字节码中的操作指令和真正的平台体系结构之间的指令做映射。比如把Java的load指令换成native code的load指令。 JIT的出现,是为了补强虚拟机边运行边解释的低性能。它会智能地对热点代码进行优化且重复利用,最终将这些代码编译为与本地平台相关的机器码。 解释器与编译器 并存架构 刚才说明了引入JIT编译器的好处,那么HotSpot JVM为什么不完全采用编译 继续阅读 >>


董恒毅 17/12/28 10:09:34
谈起GC,应该是让Java程序员最激动的一项技术,我相信每个Java程序员都有探究GC本质的冲动! 本篇博客围绕三个问题展开: 1.哪些内存需要回收? 2.什么时候回收? 3.如何回收? 哪些内存需要回收 首先回答第一个问题:不再使用的对象需要进行回收,不使用的类也有可能回收。 那么我们如何判断一个对象不再使用呢?主要有以下两种方法。 引用计数算法 定义:给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减一;任何时刻计数器为0的对象就是不会被使用的对象。 我们可以看出,引用技术方法实现简单。并且有一些GC中确实使用的是引用计数算法,但是在Java虚拟机中并没有使用这个方法进行内存管理,原因就是一个问题很难被解决—对象之间循环引用。 来看一个例子: class Node { Node next ; } Node a = new Node (); Node b = new Node (); 继续阅读 >>


董恒毅 17/12/20 20:26:28