Java 进阶
文章平均质量分 94
crossoverJie
会crossover的程序猿
展开
-
设计一个全局异常处理器
前言最近稍微闲了一点于是把这个半年都没更新的开源项目 cicada 重新捡了起来。一些新关注的朋友应该还不知道这项目是干啥的?先来看看官方介绍吧(其实就我自己写的原创 2019-07-15 08:44:25 · 175 阅读 · 1 评论 -
为自己搭建一个分布式 IM 系统二【从查找算法聊起】
前言最近这段时间确实有点忙,这篇的目录还是在飞机上敲出来了的。言归正传,上周更新了 cim 第一版:为自己搭建一个分布式 IM(即时通讯) 系统;没想到反响热烈,最高时上了 GitHub Trending Java 版块的首位,一天收到了 300+ 的 star。现在总共也有 1.3K+ 的 star,有几十个朋友参加了测试,非常感谢大家的支持。在这过程中也收到一些 bug 反馈,...原创 2019-01-14 09:01:42 · 422 阅读 · 0 评论 -
为自己搭建一个分布式 IM(即时通讯) 系统
前言大家新年快乐!新的一年第一篇技术文章希望开个好头,所以元旦三天我也没怎么闲着,希望给大家带来一篇比较感兴趣的干货内容。老读者应该还记得我在去年国庆节前分享过一篇《设计一个百万级的消息推送系统》;虽然我在文中有贴一些伪代码,依然有些朋友希望能直接分享一些可以运行的源码;这么久了是时候把坑填上了。目录结构:本文较长,高能预警;带好瓜子板凳。于是在之前的基础上我完善了一些...原创 2019-01-02 08:10:42 · 5806 阅读 · 2 评论 -
没错,老板让我写个 BUG!
前言标题没有看错,真的是让我写个 bug!刚接到这个需求时我内心没有丝毫波澜,甚至还有点激动。这可是我特长啊;终于可以光明正大的写 bug 了原创 2018-12-12 08:37:03 · 323 阅读 · 1 评论 -
一次生产 CPU 100% 排查优化实践
前言到了年底果然都不太平,最近又收到了运维报警:表示有些服务器负载非常高,让我们定位问题。还真是想什么来什么,前些天还故意把某些服务器的负载提高(没错,老板让我写个 BUG!),不过还好是不同的环境互相没有影响。定位问题拿到问题后首先去服务器上看了看,发现运行的只有我们的 Java 应用。于是先用 ps 命令拿到了应用的 PID。接着使用 ps -Hp pid 将这个进程的线程显示出来...原创 2018-12-17 08:49:46 · 248 阅读 · 0 评论 -
如何判断一个元素在亿级数据中是否存在?
前言最近有朋友问我这么一个面试题目:现在有一个非常庞大的数据,假设全是 int 类型。现在我给你一个数,你需要告诉我它是否存在其中(尽量高效)。需求其实很清晰,只是要判断一个数据是否存在即可。但这里有一个比较重要的前提:非常庞大的数据。常规实现先不考虑这个条件,我们脑海中出现的第一种方案是什么?我想大多数想到的都是用 HashMap 来存放数据,因为它的写入查询的效率都比较高。...原创 2018-11-27 11:01:23 · 1152 阅读 · 0 评论 -
分享一些 Kafka 消费数据的小经验
前言之前写过一篇《从源码分析如何优雅的使用 Kafka 生产者》 ,有生产者自然也就有消费者。建议对 Kakfa 还比较陌生的朋友可以先看看。就我的使用经验来说,大部分情况都是处于数据下游的消费者角色。也用 Kafka 消费过日均过亿的消息(不得不佩服 Kakfa 的设计),本文将借助我使用 Kakfa 消费数据的经验来聊聊如何高效的消费数据。单线程消费以之前生产者中的代码为例,...原创 2018-11-20 08:45:19 · 370 阅读 · 0 评论 -
设计一个可拔插的 IOC 容器
前言磨了许久,借助最近的一次通宵上线 cicada 终于更新了 v2.0.0 版本。之所以大的版本号变为 2,确实是向下不兼容了;主要表现为:修复了几个反馈的 bug。灵活的路由方式。可拔插的 IOC 容器选择。其中重点是后面两个。新的路由方式先来看第一个:路由方式的更新。在之前的版本想要写一个接口必须的实现一个 WorkAction;而且最麻烦的是一个实现类只能做一个接口...原创 2018-11-15 08:43:39 · 550 阅读 · 3 评论 -
不改一行代码定位线上性能问题
背景最近时运不佳,几乎天天被线上问题骚扰。前几天刚解决了一个 HashSet 的并发问题,周六又来了一个性能问题。大致的现象是:我们提供出去的一个 OpenAPI 反应时快时慢,快的时候几十毫秒,慢的时候几秒钟才响应。尝试解决由于这种也不是业务问题,不能直接定位。所以尝试在测试环境复现,但遗憾的测试环境贼快。没办法只能硬着头皮上了。中途有抱着侥幸心里让运维查看了 Nginx 里...原创 2018-11-12 08:30:37 · 346 阅读 · 0 评论 -
一次 HashSet 所引起的并发问题
背景上午刚到公司,准备开始一天的摸鱼之旅时突然收到了一封监控中心的邮件。心中暗道不好,因为监控系统从来不会告诉我应用完美无 bug,其实系统挺猥琐。打开邮件一看,果然告知我有一个应用的线程池队列达到阈值触发了报警。由于这个应用出问题非常影响用户体验;于是立马让运维保留现场 dump 线程和内存同时重启应用,还好重启之后恢复正常。于是开始着手排查问题。分析首先了解下这个应用大概是做什么...原创 2018-11-08 08:12:40 · 194 阅读 · 0 评论 -
1.6W star 的 JCSprout 阅读体验大提升
万万没想到 JCSprout 截止目前居然有将近1.6W star。真的非常感谢各位大佬的支持。年初时创建这个 repo 原本只是想根据自己面试与被面试的经历记录一些核心知识点,结果却是越写越多。在我自己宣传和其他技术大佬(包括阮大)的助攻之下连续两个月都在 GitHub trending Java片区的榜首。甚至有一次还一跃到整个 GitHub 的第一,同时还有帮助一些同学拿到了大...原创 2018-11-06 08:23:56 · 178 阅读 · 0 评论 -
一份针对于新手的多线程实践--进阶篇
前言在上文《一份针对于新手的多线程实践》留下了一个问题:这只是多线程其中的一个用法,相信看到这里的朋友应该多它的理解更进一步了。再给大家留个阅后练习,场景也是类似的:在 Redis 或者其他存储介质中存放有上千万的手机号码数据,每个号码都是唯一的,需要在最快的时间内把这些号码全部都遍历一遍。有想法感兴趣的朋友欢迎在文末留言参与讨论原创 2018-10-31 10:56:48 · 188 阅读 · 0 评论 -
一份针对于新手的多线程实践
前言前段时间在某个第三方平台看到我写作字数居然突破了 10W 字,难以想象高中 800 字作文我都得巧妙的利用换行来完成(懂的人肯定也干过原创 2018-10-29 08:13:14 · 230 阅读 · 0 评论 -
长连接的心跳及重连设计
前言说道“心跳”这个词大家都不陌生,当然不是指男女之间的心跳,而是和长连接相关的。顾名思义就是证明是否还活着的依据。什么场景下需要心跳呢?目前我们接触到的大多是一些基于长连接的应用需要心跳来“保活”。由于在长连接的场景下,客户端和服务端并不是一直处于通信状态,如果双方长期没有沟通则双方都不清楚对方目前的状态;所以需要发送一段很小的报文告诉对方“我还活着”。同时还有另外几个目的:服...原创 2019-01-23 08:53:24 · 392 阅读 · 0 评论 -
利用策略模式优化过多 if else 代码
前言不出意外,这应该是年前最后一次分享,本次来一点实际开发中会用到的小技巧。比如平时大家是否都会写类似这样的代码:if(a){ //dosomething}else if(b){ //doshomething}else if(c){ //doshomething} else{ ////doshomething}条件少还好,一旦 else if 过多这里的逻辑将会比较混乱...原创 2019-01-30 17:46:56 · 892 阅读 · 0 评论 -
What?一个 Dubbo 服务启动要两个小时!
前言前几天在测试环境碰到一个非常奇怪的与 dubbo 相关的问题,事后我在网上搜索了一圈并没有发现类似的帖子或文章,于是便有了这篇。希望对还未碰到或正在碰到的朋友有所帮助。现象现象是这样的,有一天测试在测试环境重新部署一个 dubbo 应用的时候发现应用“启动不起来”。但过几个小时候之后又能自己慢慢恢复,并能够对外提供 dubbo 服务。但其实经过我后续排查发现刚开始其实并不是启动...原创 2019-07-05 08:32:18 · 172 阅读 · 0 评论 -
常见的集合容器应当避免的坑
前言前不久帮同事一起 review 一个 job 执行缓慢的问题时发现不少朋友在撸码实现功能时还是有需要细节不够注意,于是便有了这篇文章。ArrayList 踩坑List<String> temp = new ArrayList() ;//获取一批数据List<String> all = getData();for(String str : all) { ...原创 2019-07-04 08:48:52 · 155 阅读 · 0 评论 -
再一次生产 CPU 高负载排查实践
前言前几日早上打开邮箱收到一封监控报警邮件:某某 ip 服务器 CPU 负载较高,请研发尽快排查解决,发送时间正好是凌晨。其实早在去年我也处理过类似的问题,并记录下来:《一次生产 CPU 100% 排查优化实践》不过本次问题产生的原因却和上次不太一样,大家可以接着往下看。问题分析收到邮件后我马上登陆那台服务器,看了下案发现场还在(负载依然很高)。于是我便利用这类问题的排查套路定位一遍...原创 2019-06-18 08:38:11 · 220 阅读 · 0 评论 -
线程池没你想的那么简单(续)
前言前段时间写过一篇《线程池没你想的那么简单》,和大家一起撸了一个基本的线程池,具备:线程池基本调度功能。线程池自动扩容缩容。队列缓存线程。关闭线程池。这些功能,最后也留下了三个待实现的 features 。执行带有返回值的线程。异常处理怎么办?所有任务执行完怎么通知我?这次就实现这三个特性来看看 j.u.c 中的线程池是如何实现这些需求的。再看本文之前,强烈建议...原创 2019-06-06 09:11:49 · 221 阅读 · 0 评论 -
线程池没你想的那么简单
前言原以为线程池还挺简单的(平时常用,也分析过原理),这次是想自己动手写一个线程池来更加深入的了解它;但在动手写的过程中落地到细节时发现并没想的那么容易。结合源码对比后确实不得不佩服 Doug Lea 。我觉得大部分人直接去看 java.util.concurrent.ThreadPoolExecutor 的源码时都是看一个大概,因为其中涉及到了许多细节处理,还有部分 AQS 的内容,所以想...原创 2019-05-20 08:42:43 · 306 阅读 · 0 评论 -
图床失效了?也许你应该试试这个工具
前言经过几个小伙伴的提醒,发现个人博客中的许多图片都裂了无法访问;原因就不多说,既然出现问题就得要解决。原本我的处理方式非常简单粗暴:找到原有的图片重新下载下来上传到新的可用图床再把图片地址替换。这样搞了一两篇之后我就绝望了。。。之前为了代码能在公众号里也有好的阅读体验,所以能截图的我绝不贴代码,导致一篇文章多的得有十几张图片。好在哪位大佬说过“以人肉XX为耻”,这种重复劳动力完...原创 2019-05-09 08:51:01 · 1063 阅读 · 1 评论 -
『并发包入坑指北』之向大佬汇报任务
前言目录如下:在面试过程中聊到并发相关的内容时,不少面试官都喜欢问这类问题:当 N 个线程同时完成某项任务时,如何知道他们都已经执行完毕了。这也是本次讨论的话题之一,所以本篇为『并发包入坑指北』的第二篇;来聊聊常见的并发工具。自己实现其实这类问题的核心论点都是:如何在一个线程中得知其他线程是否执行完毕。假设现在有 3 个线程在运行,需要在主线程中得知他们的运行结果;可以分为以...原创 2019-04-29 01:20:52 · 173 阅读 · 0 评论 -
『并发包入坑指北』之阻塞队列
前言较长一段时间以来我都发现不少开发者对 jdk 中的 J.U.C(java.util.concurrent)也就是 Java 并发包的使用甚少,更别谈对它的理解了;但这却也是我们进阶的必备关卡。之前或多或少也分享过相关内容,但都不成体系;于是便想整理一套与并发包相关的系列文章。其中的内容主要包含以下几个部分:根据定义自己实现一个并发工具。JDK 的标准实现。实践案例。基于这三...原创 2019-04-10 08:28:02 · 269 阅读 · 0 评论 -
一次分表踩坑实践的探讨
前言之前不少人问我“能否分享一些分库分表相关的实践”,其实不是我不分享,而是真的经验不多原创 2019-04-16 09:10:20 · 248 阅读 · 0 评论 -
线程池中你不容错过的一些细节
背景上周分享了一篇《一个线程罢工的诡异事件》,最近也在公司内部分享了这个案例。无独有偶,在内部分享的时候也有小伙伴问了之前分享时所提出的一类问题:这其实是一类共性问题,我认为主要还是两个原因:我自己确实也没讲清楚,之前画的那张图还需要再完善,有些误导。第二还是大家对线程池的理解不够深刻,比如今天要探讨的内容。线程池的工作原理首先还是来复习下线程池的基本原理。我认为线程...原创 2019-03-26 09:02:32 · 159 阅读 · 0 评论 -
一个线程罢工的诡异事件
背景事情(事故)是这样的,突然收到报警,线上某个应用里业务逻辑没有执行,导致的结果是数据库里的某些数据没有更新。虽然是前人写的代码,但作为 Bug maker&killer 只能咬着牙上了。因为之前没有接触过出问题这块的逻辑,所以简单理了下如图:有一个生产线程一直源源不断的往队列写数据。消费线程也一直不停的取出数据后写入后续的业务线程池。业务线程池里的线程会对每个任务进行...原创 2019-03-13 08:35:33 · 168 阅读 · 0 评论 -
一致性 Hash 算法的实际应用
前言记得一年前分享过一篇《一致性 Hash 算法分析》,当时只是分析了这个算法的实现原理、解决了什么问题等。但没有实际实现一个这样的算法,毕竟要加深印象还得自己撸一遍,于是本次就当前的一个路由需求来着手实现一次。背景看过《为自己搭建一个分布式 IM(即时通讯) 系统》的朋友应该对其中的登录逻辑有所印象。先给新来的朋友简单介绍下 cim 是干啥的:其中有一个场景是在客户端登录成功...原创 2019-03-01 08:42:24 · 264 阅读 · 0 评论 -
从源码分析如何优雅的使用 Kafka 生产者
前言在上文 设计一个百万级的消息推送系统 中提到消息流转采用的是 Kafka 作为中间件。其中有朋友咨询在大量消息的情况下 Kakfa 是如何保证消息的高效及一致性呢?正好以这个问题结合 Kakfa 的源码讨论下如何正确、高效的发送消息。内容较多,对源码感兴趣的朋友请系好安全带原创 2018-10-11 08:17:09 · 433 阅读 · 0 评论 -
利用责任链模式设计一个拦截器
前言近期在做 Cicada 的拦截器功能,正好用到了责任链模式。这个设计模式在日常使用中频率还是挺高的,借此机会来分析分析。责任链模式先来看看什么是责任链模式。引用一段维基百科对其的解释:责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该...原创 2018-10-22 08:19:52 · 184 阅读 · 0 评论 -
Netty(二) 从线程模型的角度看 Netty 为什么是高性能的?
前言在之前的 SpringBoot 整合长连接心跳机制 一文中认识了 Netty。但其实只是能用,为什么要用 Netty?它有哪些优势?这些其实都不清楚。本文就来从历史源头说道说道。传统 IO在 Netty 以及 NIO 出现之前,我们写 IO 应用其实用的都是用 java.io.* 下所提供的包。 比如下面的伪代码:ServeSocket serve...原创 2018-07-04 13:23:19 · 253 阅读 · 0 评论 -
一次线上问题排查所引发的思考
前言之前或多或少分享过一些内存模型、对象创建之类的内容,其实大部分人看完都是懵懵懂懂,也不知道这些的实际意义。直到有一天你会碰到线上奇奇怪怪的问题,如:线程执行一个任务迟迟没有返回,应用假死。接口响应缓慢,甚至请求超时。CPU 高负载运行。这类问题并不像一个空指针、数组越界这样明显好查,这时就需要刚才提到的内存模型、对象创建、线程等相关知识结合在一起来排查问题了。...原创 2018-07-09 09:34:36 · 499 阅读 · 1 评论 -
一个学渣的阿里之路
前言最近有些朋友在面试阿里,加上 Java-Interview 项目的原因也有小伙伴和我讨论,近期也在负责部门的招牌,这让我想起年初那段长达三个月的奇葩面试经历��。本来没想拿出来说的,毕竟最后也没成。但由于那几个月的经历让我了解到了大厂的工作方式、对候选同学的考察重点以及面试官的套路等都有了全新的认识。当然最重要的是这段时间的查漏补缺也让自己精进不少。先交代下背景吧:...原创 2018-06-22 08:25:56 · 3169 阅读 · 9 评论 -
Guava 源码分析(Cache 原理)
前言Google 出的 Guava 是 Java 核心增强的库,应用非常广泛。我平时用的也挺频繁,这次就借助日常使用的 Cache 组件来看看 Google 大牛们是如何设计的。缓存 本次主要讨论缓存。缓存在日常开发中举足轻重,如果你的应用对某类数据有着较高的读取频次,并且改动较小时那就非常适合利用缓存来提高性能。缓存之所以可以提高性能是因为它的读取效率很...原创 2018-06-13 10:21:56 · 321 阅读 · 0 评论 -
分布式限流
前言本文接着上文应用限流进行讨论。之前谈到的限流方案只能针对于单个 JVM 有效,也就是单机应用。而对于现在普遍的分布式应用也得有一个分布式限流的方案。基于此尝试写了这个组件:https://github.com/crossoverJie/distributed-redis-toolDEMO以下采用的是https://github.com/crossover...原创 2018-04-28 10:03:27 · 277 阅读 · 3 评论 -
秒杀架构实践
前言之前在 Java-Interview 中提到过秒杀架构的设计,这次基于其中的理论简单实现了一下。 本次采用循序渐进的方式逐步提高性能达到并发秒杀的效果,文章较长请准备好瓜子板凳(liushuizhang��)。本文所有涉及的代码:https://github.com/crossoverJie/SSMhttps://github.com/crossoverJie...原创 2018-05-09 10:05:29 · 1082 阅读 · 0 评论 -
动手实现一个 LRU cache
前言LRU 是 Least Recently Used 的简写,字面意思则是最近最少使用。通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被撑满。如常用的 Redis 就有以下几种策略: 策略 描述 volatile-lru 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 volatile-...原创 2018-04-08 11:22:26 · 282 阅读 · 0 评论 -
深入理解线程通信
前言开发中不免会遇到需要所有子线程执行完毕通知主线程处理某些逻辑的场景。或者是线程 A 在执行到某个条件通知线程 B 执行某个操作。可以通过以下几种方式实现:等待通知机制 等待通知模式是 Java 中比较经典的线程通信方式。两个线程通过对同一对象调用等待 wait() 和通知 notify() 方法来进行通讯。如两个线程交替打印奇偶数:pu...原创 2018-03-19 10:05:57 · 279 阅读 · 0 评论 -
你应该知道的 volatile 关键字
前言不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能。首先来看看为什么会出现这个关键字。内存可见性由于 Java 内存模型(JMM)规定,所有的变量都存放在主内存中,而每个线程都有着自己的工作内存(高速缓存)。线程在工作时,需要将主内存中的数据拷贝到工作内存中。这样对数据的任何操作都是基于工作内存(效率提高),并且不能直接操作主内存以及其他线程工...原创 2018-03-09 10:06:00 · 181 阅读 · 0 评论 -
LinkedHashMap 底层分析
众所周知 HashMap 是一个无序的 Map,因为每次根据 key 的 hashcode 映射到 Entry 数组上,所以遍历出来的顺序并不是写入的顺序。因此 JDK 推出一个基于 HashMap 但具有顺序的 LinkedHashMap 来解决有排序需求的场景。它的底层是继承于 HashMap 实现的,由一个双向链表所构成。LinkedHashMap 的排序方式有两种:根据写原创 2018-02-06 20:29:50 · 213 阅读 · 0 评论 -
对象的创建与内存分配
创建对象当 JVM 收到一个 new 指令时,会检查指令中的参数在常量池是否有这个符号的引用,还会检查该类是否已经被加载过了,如果没有的话则要进行一次类加载。接着就是分配内存了,通常有两种方式:指针碰撞空闲列表使用指针碰撞的前提是堆内存是完全工整的,用过的内存和没用的内存各在一边每次分配的时候只需要将指针向空闲内存一方移动一段和内存大小相等区域即可。当堆中已经使用的内存和原创 2018-01-18 17:22:51 · 679 阅读 · 0 评论