`

使用visual vm 分析线程(下)

阅读更多

接着上一篇《线程安全扫盲贴三》,开始第二次测试。

第二次测试

这次并发1000个客户端消息,每次并发20条后休眠1秒。客户端消息发给我的Server后,我的Server再转发给消息指定的服务器。为了产生异常消息,我将指定的目标服务器关闭了,于是每次消息第一次发送完成后,都成为了一个异常消息,每个异常消息将会自动间隔30s;1m;2m发送3次,发送失败后停止发送。

这样虽然是并发了1000个,但是服务器实际发送了4000次。

 

张上一篇中已经看过这4个线程。此图与上一篇中,最明显的就是4个线程都在分时执行了,《线程安全扫盲贴三》只有2个在执行。新加入的2个就是异常消息errorList与异常文件删除监听的两个线程。

 

 

下面看看我的线程池,我有两个线程池,一个用来执行接收到的消息,一个用来发送消息。

接收到的消息进入接收的线程池中,分析消息内容,如果需要发送出去,再加入到发送的线程池中。

根据日志打印的结果,pool-1是发送消息的线程,pool2是接收消息的线程。

 

基本上pool1发送消息线程在执行的时候,pool2接收消息线程全部在等待。

上面这句话也许不对,pool1发送消息可以很多一起并发,多个发送线程间可能无资源抢占,pool2接收消息线程不能多个并发,这也可能造成这样。

 

 

执行了一段时间之后,发现待重发的消息并没有重发,同时4个监听线程显示只有Thread3在执行了,4巨头线程另外三个都在sleeping。

查看日志发现这几个线程分别对应的监听为:

Thread-0:已发送消息删除磁盘文件监听

Thread-1:已发送错误消息删除磁盘文件监听
Thread-2:待发送消息监听

Thread-3:待重发错误消息监听

这么看情况还是很乐观的,我正希望Thread-3是在运行可以将待重发的错误消息重发出去,虽然visual vm显示Thread-3在努力的running,但是下面是Thread-3的run方法,它连心跳的那句debug都无法打出来。也许是在执行errorMessageSearcher.resendErrorMsg(startTime,endTime);方法一直没退出。。

 

Thread-3的run方法:

	public void run() {
		log.info("Thread Name="+Thread.currentThread().getName());//Hhread-3
		while(true){
			endTime = DateUtil.convertDateTOStr(new Date(), DateUtil.PALETTE_8);
			log.debug(Thread.currentThread().getName()+"查询定时发送的消息时间范围:"+startTime+"---->"+endTime);
			try {
				errorMessageSearcher.resendErrorMsg(startTime,endTime);
			} catch (IOException e1) {
				log.error(e1);
			} catch (ClientException e1) {
				log.error(e1);
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				log.error(e);
			}
		}
	}

 

跟着这个思路,刚才仔细检查了errorMessageSearcher.resendErrorMsg(startTime,endTime)方法,见下方注释掉的方法,之前是通过Lucene搜索到到点可以重发的数据后,调用客户端代码,通过socket再向我Server发一条数据过来,而现在改成了直接将要重发的消息加入到接收消息的内存List中。

	public int resendErrorMsg(String begin,String end) throws IOException, ClientException{
		if(ErrorMessageIndexer.getInstance().isHasUpdated()==true){
			ErrorMessageIndexer.getInstance().commit();
			reader = IndexReader.openIfChanged(reader);
			searcher =  new IndexSearcher(reader); 
		}
		int rtnValue = 0;
	    TermRangeQuery rangeQuery = new TermRangeQuery(ErrorMessageIndexer.NEXT_DATE_FIELD,begin, end,true,true);  ;
	    //获得得分靠前的max个匹配记录  
	    ScoreDoc[] docs = searcher.search(rangeQuery,max).scoreDocs;
	    if(docs!=null&&docs.length>0){
	    	rtnValue = docs.length;
	    	 for(int i = 0; i < docs.length; i++) { 
	    		 int docId = docs[i].doc;
	    		 Document doc = searcher.doc(docId);
		         String message = doc.get(ErrorMessageIndexer.ERROR_MESSAGE_FIELD); 
		         String uuid = doc.get(ErrorMessageIndexer.UUID_FIELD);
		         
		         //通过客户端,调用socket通信,将消息发送到infoList中去
//		         IIPayrelayClient client = new SyncIPayrelayClient();
//				 client.request(message, false);
		         
		         //直接加入到消息队列中
				 WSData wsData = new WSData();
				 wsData.setMessage(message);
		         InfoReceiveThreadPoolManager.getInstance().addInfoQueue(wsData);
		         
				 //删除索引
				 log.debug("删除索引开始:"+uuid);
			     ErrorMessageIndexer.getInstance().deleteWSData(uuid);
			     log.debug("删除索引结束:"+uuid);
	    	 }  
	    }
	    return rtnValue;
	}

 

通过这样修改后,1000条数据重发4次都顺利完成了,完成后Thread-3又回到了休眠状态。

 

第三次测试

像上面那么改了之后,并发1000条是轻松的就处理完了,于是测试了一下1w条异常数据的情况,这下苦逼了。

pool2全部都堵塞了在等锁,不过pool1都空了。

 

这个也很好解释,上面java代码中的这句:

InfoReceiveThreadPoolManager.getInstance().addInfoQueue(wsData);

导致异常的消息不用再进入发送消息队列了,直接写如了接收队列,于是接收队线程池很紧张了,发送线程池则等待接收到的消息转到发送线程池中,暂时还表示无压力,过一会儿之后可以看到发送线程池开始绿了~

 

我的Server是用的QuickServer实现的。通过实现QSAdmin的方法,打印了当时的线程情况。

1032条在infoList中等待发送,7747条数据出错等待到点重发。活动的发送消息线程池中线程为0,活动的接收消息线程池中线程为100(也就是我设置的最大值)。

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

今天一边写这个blog,一边解决我的问题了,遇到想起可以优化的再来完善,完全直播。

顺便摸索着学习了把怎么用visual vm分析问题。很多时候还是靠灵光一现就发现了漏洞,慢慢积累灵光就会越来越多~~

分享到:
评论

相关推荐

    visual vm虚拟机相关分析。

    3. **线程分析**:Visual VM提供线程的详细视图,显示线程状态、阻塞原因以及死锁检测,帮助调试多线程问题。 4. **方法和类的性能分析**:可以追踪方法调用和类加载,了解哪些代码段执行时间较长,优化性能关键...

    Visual VM1.3.6

    2. **CPU使用情况**:Visual VM可以帮助开发者追踪应用程序的CPU使用率,显示哪个线程或方法占用了最多的计算资源。这对于定位CPU瓶颈至关重要。在"CPU"视图中,你可以看到每个线程的调用堆栈,帮助定位导致高CPU...

    Visual VM 1.3.8 中文版

    Visual VM 提供了查看和分析线程状态的能力,包括线程的挂起、等待、阻塞等状态,这对于调试多线程问题非常有帮助。 3. **CPU性能分析**:通过CPU视图,开发者可以查看哪些方法消耗了最多的CPU时间,从而找出性能...

    Visual VM的GC插件

    Visual VM是一款强大的Java性能分析工具,它集成了多种功能,如内存分析、线程分析、CPU剖析以及JVM垃圾收集(GC)监视。其中,GC插件是Visual VM的一个重要组成部分,用于深入理解Java应用程序的内存管理和垃圾收集...

    visual VM配置JConsole plugin JTop.jar

    Visual VM是一款强大的Java性能分析工具,它包含了丰富的功能,如CPU和内存监控、线程分析、JMX连接等。在Java开发和运维过程中,我们常常使用Visual VM来诊断和优化应用性能。而JConsole则是另一个Java性能监视工具...

    如何在Visual Studio 10.0中设置Halcon机器视觉

    比如路径X:\ProgramFiles\MVTec\HALCON-10.0\bin\dotnet20下无法使用,而X:\ProgramFiles\MVTec\HALCON-10.0\bin\dotnet35下可以使用。这通常与.net框架版本不匹配有关。 - **控件无法显示图片**:如果在使用Halcon...

    JVisualVM进行性能分析中,jconsole需要的jtop插件

    JVisualVM是一款集成化工具,它包含了多种Java应用性能分析功能,如监视CPU使用率、内存状况、线程状态、类加载、垃圾收集等。JVisualVM不仅能够本地运行,还可以远程连接到其他正在运行的Java进程,为开发者提供了...

    远程线程注入_远程_远程线程_dll注入_注入_

    在提供的压缩包文件中,"远程线程注入.sln"是一个Visual Studio解决方案文件,很可能包含了实现上述步骤的源代码项目。"Debug"和".vs"目录通常包含编译过程中产生的中间文件和配置信息。"远程线程注入"可能是源代码...

    Visual Gc插件 亲测适用于jdk1.6.0_45

    它与JVisualVM(Java Visual VM)紧密集成,提供了图形化的界面,帮助用户直观地理解Java虚拟机(JVM)的内存管理和垃圾回收过程。在本文中,我们将深入探讨Visual GC插件在JDK 1.6.0_45版本中的实际应用和其核心...

    如何获取系统指定进程线程信息

    本教程将深入探讨如何使用C++ .NET语言在Visual Studio .NET环境下编写程序来实现这一功能。 首先,我们需要了解Windows API提供的相关函数。在Windows操作系统中,我们可以调用`CreateToolhelp32Snapshot`、`...

    VM版 wince6.0系统

    4. **性能优化**:虚拟环境下可能会影响系统性能,合理调整虚拟机的CPU和内存资源分配,以及使用合适的虚拟化技术,如VT-x或AMD-V,有助于提升运行效率。 5. **安全性考虑**:由于虚拟机与主机共享资源,必须注意...

    visualVM&插件

    它允许开发者深入了解JVM(Java虚拟机)的内部工作,包括内存使用、CPU消耗、线程状态以及方法调用等信息。VisualVM提供了丰富的可视化界面,使得开发者能够方便地监控和诊断Java应用程序的性能问题。 标题中的...

    EDA/PLD中的用Visual C++实现远程线程嵌入技术

    `OpenProcess`函数用于获取对目标进程的访问权限,参数如`PROCESS_CREATE_THREAD`, `PROCESS_VM_OPERATION`, 和 `PROCESS_VM_WRITE`分别允许创建线程、执行虚拟内存操作和写入虚拟内存。如果没有足够的权限,就需要...

    VisualVM-入门指南.docx

    这些工具与 JDK 的标准版本是一致的,可以使用 VisualVM 生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析。 如何获取 VisualVM VisualVM 是一个免费的工具,可以从官方网站下载。下载完成...

    visualvm中文版

    它集成了多种功能,包括内存分析、线程检查、CPU使用率监控、类加载和垃圾回收查看等,能够帮助开发者深入理解Java应用程序的运行状态。 标题中的"visualvm中文版"指的是该工具提供了中文界面,使得中国用户在使用...

    使用Netbeans和Visual Studio调试JNI应用程序

    2. 在"配置属性"中,选择"多线程DLL",并确保使用与Java相同的编译器版本,这里是VC9.0。 3. 编写JNI函数,遵循JNI头文件(如`jni.h`)定义的规范。这些函数需要与Java中的方法签名匹配。 在Netbeans中配置JNI项目...

    visualmodeler

    当Visual Modeler与GridSim结合使用时,用户可以通过Visual Modeler设计网格环境的模型,然后利用GridSim进行仿真和分析。例如,用户可以在Visual Modeler中定义不同类型的资源、用户需求以及任务属性,包括计算量、...

    计算机软件-商业源码-171 获取内存使用信息.zip

    4. **内存分析工具**:除了编写源码实现,还可以借助各种内存分析工具,如Valgrind(跨平台)、Visual Studio的诊断工具、Java的VisualVM等,它们能提供更直观的内存使用报告,帮助定位问题。 5. **性能优化**:...

Global site tag (gtag.js) - Google Analytics