【CountDownLatch】死循环检测模板/多线程重复测试模板

意义:

CountDownLatch的一个作用是检测死循环,因为死循环不容易复现,需要把一个程序执行多次。

有的同学会用脚本循环执行,如果没有linux环境,还得装环境,有点麻烦。

所以想到直接用Java实现重复执行一段代码的功能。


注意:

0、其实,HashMap的死循环不好复现,且没什么实际意义。并发本身就是会出各种各样的问题,本文的价值更多体现在怎么用JMC查看死循环,以及怎么用模板循环测试代码片段。

1、JDK1.8在TreeNode.split()中死循环

2、MapOper中的for循环,次数要设置大一些,设置为100,基本复现不了,设置为50000,到61就复现了。

3、put操作进行try catch,因为并发操作经常出现exception,中断循环,阻碍死循环的复现。


结果如下:

LoopTime: 6217
LoopTime: 6218
LoopTime: 6219
LoopTime: 6220 --》卡在这


有时候会报内存泄漏错误

Exception in thread "Thread-124" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.replacementNode(Unknown Source)
at java.util.HashMap$TreeNode.untreeify(Unknown Source)
at java.util.HashMap$TreeNode.split(Unknown Source)
at java.util.HashMap.resize(Unknown Source)
at java.util.HashMap.putVal(Unknown Source)
at java.util.HashMap.put(Unknown Source)
at multithread.CountDownLatchForInfinitLoop$MapOper.run(CountDownLatchForInfinitLoop.java:47)
at java.lang.Thread.run(Unknown Source)

可能因为resize()一直在循环,导致某些对象不能回收,最终内存泄漏,这块具体还没分析。


用jmc.exe工具(在JDK的bin目录下)可以看到,线程堆栈一直停在split()方法了,说明这里有死循环

【CountDownLatch】死循环检测模板/多线程重复测试模板_第1张图片

CountDownLatch在本例子的作用是,每次Loop都等线程执行完了,再执行下一次loop,如果某一次出现死循环,则countDown()不会被执行,loop就会被hang在某次循环。

本篇是在:【CountDownLatch实例】主线程等待其它线程执行完毕 的基础之上进行修改的


参考:hashmap死循环示例及检测方法。 


---------------------------------------------

package multithread;

import java.util.HashMap;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchForInfinitLoop {
	
	public static void loopOper() throws InterruptedException{
		CountDownLatchForInfinitLoop test = new CountDownLatchForInfinitLoop();

		CountDownLatch latch = new CountDownLatch(2);
		HashMap map = new HashMap(2);
		
		Thread t1 = new Thread(test.new MapOper(latch,map));
		Thread t2 = new Thread(test.new MapOper(latch,map));
		
	/*	t1.setName("Thread1");
		t2.setName("Thread2");*/
		t1.start();
		t2.start();
		latch.await();
	}
	
	public static void main(String[] args) throws InterruptedException {
		
		
		for (int i = 0; i < 1000000; i++) {
			loopOper();
			System.out.println("LoopTime: "+i);
		}
		
	}
	
	public class MapOper implements Runnable {
		
		CountDownLatch latch ;
		HashMap map;
		int i;

		public MapOper(CountDownLatch latch, HashMap map) {
			this.latch = latch;
			this.map = map;
			this.i = i;
		}

		public void run() {
			
			for (int i = 0; i < 50000; i++) {
				try {

					map.put(String.valueOf(i),i);
				} catch (Exception e) {
					System.out.println("put value exception");
				}
			}
			
			latch.countDown();
		}
	}
}


你可能感兴趣的:(多线程设计)