今天RP爆发,16核服务器load飙到30多,cpu使用情况全部99%以上。

从jstack中分析发现全部线程都堵在map.transfer处,如下:

"pool-10-thread-23" prio=10 tid=0x00007fb190003800 nid=0x6350 runnable [0x00007fb64554b000]
java.lang.Thread.State: RUNNABLE
at java.util.LinkedHashMap.transfer(LinkedHashMap.java:253)
at java.util.HashMap.resize(HashMap.java:564)
at java.util.HashMap.addEntry(HashMap.java:851)
at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:427)
at java.util.HashMap.put(HashMap.java:484)

定位问题:

LinkedHashMap非线程安全(本来是借用linkedHashMap实现LRUCache)

问题分析:

详见:http://coolshell.cn/articles/9606.html

问题解决:

采用google的ConcurrentLinkedHashMap(https://code.google.com/p/concurrentlinkedhashmap/

Features
LRU page replacement policy (currently being upgraded to LIRS).
Equivalent performance to ConcurrentHashMap under load.
Can bound by the size of the values (e.g. Multimap cache).
Can notify a listener when an entry is evicted.

cassandra也在concurrentLinkedHashMap的基础上实现了LRUCache,代码如下(微调):

/**
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/ import java.util.Set;
import java.util.concurrent.atomic.AtomicLong; import com.googlecode.concurrentlinkedhashmap.Weighers;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; public class LRULinkedHashMap<K, V> {
public static final int DEFAULT_CONCURENCY_LEVEL = 64; private final ConcurrentLinkedHashMap<K, V> map;
private final AtomicLong requests = new AtomicLong(0);
private final AtomicLong hits = new AtomicLong(0);
private final AtomicLong lastRequests = new AtomicLong(0);
private final AtomicLong lastHits = new AtomicLong(0);
private volatile boolean capacitySetManually; public LRULinkedHashMap(int capacity) {
this(capacity, DEFAULT_CONCURENCY_LEVEL);
} public LRULinkedHashMap(int capacity, int concurrency) {
map = new ConcurrentLinkedHashMap.Builder<K, V>().weigher(Weighers.<V> singleton())
.initialCapacity(capacity).maximumWeightedCapacity(capacity)
.concurrencyLevel(concurrency).build();
} public void put(K key, V value) {
map.put(key, value);
} public V get(K key) {
V v = map.get(key);
requests.incrementAndGet();
if (v != null)
hits.incrementAndGet();
return v;
} public V getInternal(K key) {
return map.get(key);
} public void remove(K key) {
map.remove(key);
} public long getCapacity() {
return map.capacity();
} public boolean isCapacitySetManually() {
return capacitySetManually;
} public void updateCapacity(int capacity) {
map.setCapacity(capacity);
} public void setCapacity(int capacity) {
updateCapacity(capacity);
capacitySetManually = true;
} public int getSize() {
return map.size();
} public long getHits() {
return hits.get();
} public long getRequests() {
return requests.get();
} public double getRecentHitRate() {
long r = requests.get();
long h = hits.get();
try {
return ((double) (h - lastHits.get())) / (r - lastRequests.get());
} finally {
lastRequests.set(r);
lastHits.set(h);
}
} public void clear() {
map.clear();
requests.set(0);
hits.set(0);
} public Set<K> getKeySet() {
return map.keySet();
}
}

  

测试:

public static void main(String[] args) {
LRULinkedHashMap<Integer, Integer> cache = new LRULinkedHashMap<Integer, Integer>(5);
Random r = new Random();
for (int i = 0; i < 10; i++) {
int k = r.nextInt(10);
System.out.println("input " + k);
cache.put(k, k);
System.out.println(cache.getKeySet().toString());
}
}

结果如下:

input 1
[1]
input 0
[0, 1]
input 3
[0, 1, 3]
input 4
[0, 1, 4, 3]
input 2
[0, 2, 1, 4, 3]
input 2
[0, 2, 1, 4, 3]
input 4
[0, 2, 1, 4, 3]
input 8
[0, 8, 2, 4, 3]
input 0
[0, 8, 2, 4, 3]
input 2
[0, 8, 2, 4, 3]

  

Java HashMap的死循环 以及 LRUCache的正确实现的更多相关文章

  1. HashMap的原理与实 无锁队列的实现Java HashMap的死循环 red black tree

    http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html https://zh.wikipedia.org/wiki/%E7%BA ...

  2. 【转】Java HashMap的死循环

    问题的症状 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问题,所以需要变成多线程的,于是,变成多线程后到了线上,发现 ...

  3. Java HashMap的死循环

    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造 成Race Condition,从而导致死循环.这个事情我4 ...

  4. Java HashMap并发死循环

    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...

  5. 疫苗:JAVA HASHMAP的死循环

    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...

  6. Java - HashMap 多线程安全解析

    HashMap多线程并发问题分析 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问 ...

  7. 多线程下HashMap的死循环问题

    多线程下[HashMap]的问题: 1.多线程put操作后,get操作导致死循环.2.多线程put非NULL元素后,get操作得到NULL值.3.多线程put操作,导致元素丢失. 本次主要关注[Has ...

  8. JDK(九)JDK1.7源码分析【集合】HashMap的死循环

    前言 在JDK1.7&1.8源码对比分析[集合]HashMap中我们遗留了一个问题:为什么HashMap在调用resize() 方法时会出现死循环?这篇文章就通过JDK1.7的源码来分析并解释 ...

  9. 图解集合5:不正确地使用HashMap引发死循环及元素丢失

    问题引出 前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死 ...

随机推荐

  1. thrift使用案例

    参考资料:http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/ 首先是定义thrift IDL接口,如下(SunTelTc.thri ...

  2. php基础-1

    php规范 php文件以<?php开头,以?>结尾. php可以和html代码混写,若当前文件为纯php代码 ,则不用写php结尾 php的一行代码以";"(分号)结尾 ...

  3. (12)模板语言-with

    with的用处 当一个变量特别特别长,可以用with给这个变量重命名 views.py from django.shortcuts import render,HttpResponse def ind ...

  4. 流程控制之if

    流程控制 假如把写程序比做走路,那我们到现在为止,一直走的都是直路,还没遇到过分叉口,想象现实中,你遇到了分叉口,然后你决定往哪拐必然是有所动机的.你要判断那条岔路是你真正要走的路,如果我们想让程序也 ...

  5. tomcat localhost

    启动tomcat后,登录本地localhost时,被要求输入用户名和密码,自己也从没有设置过啊,上网查找,原因如下: 机器装的oracle,它自带的httpserver的端口是8080,同时,tomc ...

  6. 如何查看你的VPS是什么虚拟化架构?

    使用virt-what即可了 CentOS安装 virt-what yum install virt-what Debian/ubuntu 安装 virt-what apt-get install v ...

  7. 【BZOJ2120】数颜色

    看代码学习好,好学好懂好ac 原题: 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中 ...

  8. 【liunx】date命令总结

    命令简介: date 根据给定格式显示日期或设置系统日期时间.print or set the system date and time 指令所在路径:/bin/date 命令语法: date [OP ...

  9. 解决GitHub下载速度比较慢

    第一步,打开本机上的Hosts文件 首先,什么是Hosts文件? 在互联网协议中,host表示能够同其他机器互相访问的本地计算机.一台本地机有唯一标志代码,同网络掩码一起组成IP地址,如果通过点到点协 ...

  10. 利用 groupby apply list 分组合并字符

    利用 groupby apply list 分组合并字符 因为需要对数据进行分组和合并字符,找到了以下方法. 有点类似 SQL 的 Group BY. import pandas as pd impo ...