误用WeakHashMap引起的死循环cpu跑满问题
2017-11-04 19:49
471 查看
最近使用mvel 2.2.0.Final,出现一次cpu跑满,经过线程栈分析,发现是误用WeakHashMap引起的。
故障现场:
看WeakHashMap源码:
线程在WeakHashMap的get方法里面出不来了,一直在while循环里面。
多线程并发get和put,fullgc或gc的时候可能会出现。
因为gc会把对象给清理掉,然后get方法内的while循环一直找不到eq的对象,循环出不来。
WeakHashMap类已经说明了这个类不是线程安全的。在[2.1.8.Final,~]以上修复了,除了2.2.0.Final,修复详情。
问题复现:
故障现场:
看WeakHashMap源码:
public V get(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int index = indexFor(h, tab.length); Entry<K,V> e = tab[index]; while (e != null) { if (e.hash == h && eq(k, e.get())) return e.value; e = e.next; } return null; }
线程在WeakHashMap的get方法里面出不来了,一直在while循环里面。
多线程并发get和put,fullgc或gc的时候可能会出现。
因为gc会把对象给清理掉,然后get方法内的while循环一直找不到eq的对象,循环出不来。
WeakHashMap类已经说明了这个类不是线程安全的。在[2.1.8.Final,~]以上修复了,除了2.2.0.Final,修复详情。
问题复现:
import java.util.Map; import java.util.Random; import java.util.WeakHashMap; public class WeakHashMapTest { Thread thread = new Thread(new Runnable() { @Override public void run() { } }); public static void main(String[] args) throws InterruptedException { Random random = new Random(); // Map<String, String> weak = Collections.synchronizedMap(new WeakHashMap<>());//OK Map<String, String> weak = new WeakHashMap<>(); for (int i = 0; i < 10; i++) { weak.put(new String("" + i), "" + i); } for (int i = 0; i < 20; i++) { new Thread(new Runnable() { @Override public void run() { StringBuffer sb = new StringBuffer(); for (int k = 0; k < 200; k++) { sb.append(weak.get(new String("" + (k) % 10))); if (k % 17 == 0) { System.gc(); } int nextInt = random.nextInt(10); weak.put(new String("" + nextInt), "" + nextInt); } System.out.println("end:" + sb.toString()); } }).start(); } System.gc(); System.out.println("sleep"); Thread.sleep(10000); System.out.println("exit"); System.out.println("exit2"); } static void test1() { Map<String, String> weak = new WeakHashMap<>(); weak.put(new String("1"), "1"); weak.put(new String("2"), "2"); weak.put(new String("3"), "3"); weak.put(new String("4"), "4"); weak.put(new String("5"), "5"); weak.put(new String("6"), "6"); System.out.println(weak.size()); System.gc(); //手动触发 Full GC try { Thread.sleep(50); //我的测试中发现必须sleep一下才能看到不一样的结果 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(weak.size()); } }
相关文章推荐
- 并发场景下HashMap死循环导致CPU100%的问题
- java中HashMap在多线程环境下引起CPU100%的问题解决
- 不正当使用HashMap导致cpu 100%的问题追究(HashMap死循环探究)
- HashMap 死循环 CPU100%的问题分析
- HashMap1.8中多线程扩容引起的死循环问题
- java中HashMap在多线程环境下引起CPU100%的问题解决(转)
- 并发场景下HashMap死循环导致CPU100%的问题
- HashMap多线程引起的死循环的原因分析
- HashMap 死循环的问题
- windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码
- windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码
- Java之HashMap在多线程情况下导致死循环的问题
- HashMap多线程调用下的死循环问题
- 解析java的hashmap死循环问题
- JAVA中hashmap.get()导致CPU占用过高问题
- 漫画:高并发下的HashMap引起的链表死循环原因分析
- python类中显示重写__del__方法,引起循环引用的对象无法释放,造成垃圾泄露问题
- 云计算之路-阿里云上:对“黑色n秒”问题的最终猜想——CPU C-states引起的
- 多线程下HashMap的死循环问题
- while(true)循环与CPU占用率问题