原文地址:http://hellojava.info/?p=464

最近出了个故障,排查的时候耗费了很长的时间,回顾整个排查过程,经验主义在这里起了不好的作用,直接导致了整个故障排查的时间非常长,这个故障的根本原因在于BlockingQueue用的有问题,顺带展开说说Java中常用的几个BlockingQueue:ArrayBlockingQueue、LinkedBlockingQueue和SynchronousQueue。

当时故障的现象是应用处理请求的线程池满了,导致请求处理不了,于是dump线程,看线程都在做什么,结果发现线程都Block在写日志的地方,以前出现过很多次问题,去线程dump的时候看到也是一堆的block在写日志,但通常是别的原因引发的,所以这次也是按照这样的经验,认为肯定不会是写日志这个地方的问题,于是各种排查…折腾了N久后,回过头看发现持有那把日志锁的地方是自己人写的代码,那段代码在拿到了这个日志锁后,从线程堆栈上看,block在了ArrayBlockingQueue.put这个地方,于是翻看这段代码,结果发现这是个1024长度的BlockingQueue,那就意味着如果这个Queue被放了1024个对象的话,put就一定会被block住,而且其实翻代码的时候能看出写代码的同学是考虑到了BlockingQueue如果满了应该要处理的,代码里写着:

if (blockingQueue.remainingCapacity() < 1) { //todo } blockingQueue.put 

这里两个悲催的问题,一是这个if判断完还是直接会走到put,而不是else,二是竟然关键的满了后的处理逻辑还在//todo...
另外我觉得这段代码还反应了同学对BlockingQueue的接口不太熟,要达到这个效果,不需要这样先去判断,更合适的做法是用blockingQueue.offer,返回false再做相应的异常处理。

BlockingQueue是在生产/消费者模式下经常会用到的数据结构,通常常用的主要会是ArrayBlockingQueue、LinkedBlockingQueue和SynchronousQueue。

ArrayBlockingQeue/LinkedBlockingQueue两者的最大不同主要在于存放Queue中对象方式,一个是数组,一个是链表,代码注释里也写到了两者的不同:
Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.

SynchronousQueue是一个非常特殊的BlockingQueue,它的模式是在offer的时候,如果没有另外一个线程正在take或poll的话,那么offer就会失败;在take的时候,如果没有另外的线程正好并发在offer,也会失败,这种特殊的模式非常适合用来做要求高响应并且线程出不固定的线程池的Queue。

对于在线业务场景而言,所有的并发,外部访问阻塞的地方的一个真理就是一定要有超时机制,我不知道见过多少次由于没有超时造成的在线业务的严重故障,在线业务最强调的是快速处理掉一次请求,所以fail fast是在线业务系统设计,代码编写中的最重要原则,按照这个原则上面的代码最起码明显犯的错误就是用put而不是带超时机制的offer,或者说如果是不重要的场景,完全就应该直接用offer,false了直接抛异常或记录下异常即可。

对于BlockingQueue这种场景呢,除了超时机制外,还有一个是队列长度一定要做限制,否则默认的是Integer.MAX_VALUE,万一代码出点bug的话,内存就被玩挂了。

说到BlockingQueue,就还是要提下BlockingQueue被用的最多的地方:线程池,Java的ThreadPoolExecutor中有个参数是BlockingQueue,如果这个地方用的是ArrayBlockingQueue或LinkedBlockingQueue,而线程池的coreSize和poolSize不一样的话,在coreSize线程满了后,这个时候线程池首先会做的是offer到BlockingQueue,成功的话就结束,这种场景同样不符合在线业务的需求,在线业务更希望的是快速处理,而不是先排队,而且其实在线业务最好是不要让请求堆在排队队列里,在线业务这样做很容易引发雪崩,超出处理能力范围直接拒绝抛错是相对比较好的做法,至于在前面页面上排队什么这个是可以的,那是另外一种限流机制。

所以说在写高并发、分布式的代码时,除了系统设计外,代码细节的功力是非常非常重要的。

从一个故障说说Java的三个BlockingQueue的更多相关文章

  1. 从零开始实现一个简易的Java MVC框架(三)--实现IOC

    Spring中的IOC IoC全称是Inversion of Control,就是控制反转,他其实不是spring独有的特性或者说也不是java的特性,他是一种设计思想.而DI(Dependency ...

  2. Java EE : 三、图解Session(会话)

    目录 Java EE : 一.图解Http协议 Java EE : 二.图解 Cookie(小甜饼) Java EE : 三.图解Session(会话) 概述 一.Session由来 二.Sessio ...

  3. JAVA第三周作业(从键盘输入若干数求和)

    JAVA第三周作业(从键盘输入若干数求和) 在新的一周,我学习了JAVA的IO编程.下面的代码实现了从键盘输入若干数求和的目标.import java.util.Scanner; public cla ...

  4. [Java面试三]JavaWeb基础知识总结.

    1.web服务器与HTTP协议 Web服务器 l WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. l Internet上供外界访问的Web资源分为: • 静 ...

  5. 搭建一个完整的Java开发环境

    搭建一个完整的Java开发环境 作为一个Java程序员,配置一个java开发环境是必备的技能,今天给广大菜鸟初学者补上一课.环境的配置,大概就分三个1,JDK 2,Tomcat(或者其他的)3,ecl ...

  6. Java的三种代理模式

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  7. Java的三种代理模式简述

    本文着重讲述三种代理模式在java代码中如何写出,为保证文章的针对性,暂且不讨论底层实现原理,具体的原理将在下一篇博文中讲述. 代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下, ...

  8. Effective Java 第三版——2. 当构造方法参数过多时使用builder模式

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. excel中将字符转换为数值

    EXCEL表格的左上角那个绿色符号是什么?怎么样可以转换成数值 如果你说的文本是由纯数字组成的,不包含字母和其他字符的话,那么,你要指改为数值可以这样操作:1.先在一个单元格内输入数字12.将刚才输入 ...

  2. 整数划分问题-解法汇总(暂有DP-递归)

    整数划分问题是一个锻炼组合数学,递归以及动态规划很好的例子,虽然问题看似简单,但是其中玄机万千,有人转化成为背包问题,有人用生成函数解,有人以此作为企业面试题目,可见这种问题的认可度还是很高的. 整数 ...

  3. 3.SpringMVC修改配置文件路径和给界面传递数据

    1.修改配置文件路径  达到  配置多文件的目的 web.xml文件中基础配置有springMVC配置的servlet路径 <servlet-name>SpringMVC</serv ...

  4. KMP单模快速字符串匹配算法

    KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...

  5. jquery.base64.js简单使用

    jquery.base64.js, 加密,使用,先引入jquery,然后引入jquery.base64.js 使用如下 js中加密如下 $.base64.encode(result[i].ipadre ...

  6. HDU 5920 Ugly Problem 高精度减法大模拟 ---2016CCPC长春区域现场赛

    题目链接 题意:给定一个很大的数,把他们分为数个回文数的和,分的个数不超过50个,输出个数并输出每个数,special judge. 题解:现场赛的时候很快想出来了思路,把这个数从中间分为两部分,当位 ...

  7. iOS MRC ARC 内存管理

    转自:http://www.jianshu.com/p/48665652e4e4 1. 什么是内存管理 程序在运行的过程中通常通过以下行为,来增加程序的的内存占用 创建一个OC对象 定义一个变量 调用 ...

  8. IOS-多线程技术

    三种: •NSThread: –优点:NSThread 比其他两个轻量级,使用简单 –缺点:需要自己管理线程的生命周期.线程同步.加锁.睡眠以及唤醒等.线程同步对数据的加锁会有一定的系统开销 •NSO ...

  9. apache vhost

    httpd.conf: Include "F:/wamp/alias/*" <Directory "F:\wamp\www">    Options ...

  10. SQL基本CRUD

    --已知Oracle的Scott用户中提供了三个测试数据库表 --名称分别为dept,emp,salgrade.使用SQL语言完成一下操作 --1,查询20号部门的所有员工信息: SELECT * F ...