论坛首页 Java企业应用论坛

“导出excel”压力测试多并发引起的多线程冲突问题

浏览 15448 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-10-28  
或者是将那三个全局变量设置成为局部变量
0 请登录后投票
   发表时间:2011-10-28  
花飘零_坚强的小石头 写道
或者是将那三个全局变量设置成为局部变量

建议new一个吧,每个上传使用一个实例,Servlet又不是线程安全的,不要在Servlet或Action中声明全局变量。
0 请登录后投票
   发表时间:2011-10-28  
linenlin01 写道
每个Export new 一个 TestExcelExport 对象!!!如果出现OOM,你得考虑换一个写Excel的方式,拒绝POI,拒绝JXL。用文件流来写,避免创建太多对象,导致OOM。

POI,JXL这种都是每个CELL一个OBJECT,很多字节的
当初也用过以二进制流写成BIFF格式,网上有个例子,还有个BUG,改了一个 << 操作的地方才可以的
但是发现用EXCEL 2003还是2007打开后,不能修改,格式也不好控制

LZ试下BIRD-X
0 请登录后投票
   发表时间:2011-10-28  
linenlin01 写道
每个Export new 一个 TestExcelExport 对象!!!如果出现OOM,你得考虑换一个写Excel的方式,拒绝POI,拒绝JXL。用文件流来写,避免创建太多对象,导致OOM。

自己写这些工具,如果要实现完善的功能,需要自己花大量精力,所做的工作已经脱离了项目开发的工作了(除非项目本身就是为了开发这个工具),得不偿失!
0 请登录后投票
   发表时间:2011-10-28  
解决这个问题容易,大家都给出了很好的解答。难的是这种设计遍及整个应用。LZ需要全部代码都看看啊。
0 请登录后投票
   发表时间:2011-10-28   最后修改:2011-10-28
晕,用fork() / join()啊。
大数据量excel导出,并发不是问题。
容易内存不足才是真正的问题。

以下是公司内部文档。

SQL部分
Mysqlで大量データ(10w件ぐらい)をselectしたら、「java.sql.SQLException: something wrong caused by java.lang.OutOfMemoryError: Java heap space」が発生します。
解決方法
SQL部分は改ページの方式で検索を行います。10000行/回で、Loop処理にします。
検索際、リターン値が (List<DataMap>)タイプです。その際、「at java.util.HashMap.newValueIterator(HashMap.java:843)」例外が起こします。
1.解決方法:arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
                  从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。http://forums.sun.com/thread.jspa?threadID=5245397
2.解決方法:不制作一个大数组,根据查询的结果来实现业务处理逻辑。

POI部分
POI在创建cell的时候消耗了大量的内存,没有及时回收。
1.解決方法:多调用flush(),但对于nW件的效果不明显。
2.解決方法: http://www.docjar.org/html/api/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java.html
                  a. create a template workbook, create sheets and global objects such as cell styles, number formats, etc.
                  b. create an application that streams data in a text file.(Writer fw = new OutputStreamWriter(new FileOutputStream(tmp), "UTF8"); )
                  c. Substitute the sheet in the template with the generated data.
0 请登录后投票
   发表时间:2011-10-28  
ddkk 写道
linenlin01 写道
每个Export new 一个 TestExcelExport 对象!!!如果出现OOM,你得考虑换一个写Excel的方式,拒绝POI,拒绝JXL。用文件流来写,避免创建太多对象,导致OOM。

POI,JXL这种都是每个CELL一个OBJECT,很多字节的
当初也用过以二进制流写成BIFF格式,网上有个例子,还有个BUG,改了一个 << 操作的地方才可以的
但是发现用EXCEL 2003还是2007打开后,不能修改,格式也不好控制

LZ试下BIRD-X



谢谢大家都给了很好的建议,我试试看

抽空了解下 ddkk 提到的  BIRD-X
0 请登录后投票
   发表时间:2011-10-28  
如果对实时性要求不高的话建议可以采取异步的方式,点了之后可以某个位置生成报告稍后让客户查看。后台的话就是做了一套逻辑封装一个队列依次执行,这样肯定不会有oom的问题,如果实时性要求较高的话,可以测试下,采用对象池把这些对象先虚拟出来要用时,直接取,并发大的话,就对上限做个限制,人多个话,只能稍候再试,对象池多大这个要看内存及并发需求来看了
0 请登录后投票
   发表时间:2011-10-28  
ddkk 写道
linenlin01 写道
每个Export new 一个 TestExcelExport 对象!!!如果出现OOM,你得考虑换一个写Excel的方式,拒绝POI,拒绝JXL。用文件流来写,避免创建太多对象,导致OOM。

POI,JXL这种都是每个CELL一个OBJECT,很多字节的
当初也用过以二进制流写成BIFF格式,网上有个例子,还有个BUG,改了一个 << 操作的地方才可以的
但是发现用EXCEL 2003还是2007打开后,不能修改,格式也不好控制

LZ试下BIRD-X



其实我更喜欢直接写出html文本流,然后加一个xls扩展名:)
0 请登录后投票
   发表时间:2011-10-28  
package test;

import hibernate.util.HibernateUtil;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SQLQuery;
import org.hibernate.Session;




public class FileGenerateThread{
	private static Log log = LogFactory.getLog(FileGenerateThread.class);
	
	public static void main(String[] args){
		String condition=" and 所在城市 like '南平%'";
		String filepath="D://020的桌面文件//号百//20111015 数据//xls//";
		String filename="南平";
		(new FileGenerateThread()).run(filepath, filename, condition);
	}
	
	public void run(String filepath, String filename,String condition) {
		try{
			
			  
			Session hsession=HibernateUtil.currentSession();
			String sql="select  企业名称,父企业名称,电话,  地址,  行业编码,  行业名称,  所在城市 , 网址  ,电子邮件  ,联系人,  联系电话,  传真号码  ,'' \"所在社区\"  ,企业介绍信息  ,别名 from hb_all_20111015  t where 1=1";
			String count_sql="select to_char(count(*)) from hb_all_20111015  t where 1=1";
			
			//临时变量
			Object[] obj;
			//统计信息
			SQLQuery query=hsession.createSQLQuery(count_sql+condition);
			String total_record=(String)(query.list().get(0));
			
			List list;
			int index_start=0;
			int max_record=1000;
			int i=1; //excel 行
			
			//文件变量
			File workbook;//当前文件
			String current_filename=null;//当前文件名
			BufferedOutputStream bos=null;//文件输入流
			OutputStreamWriter writer=null;//文件写头
			
			
			while(index_start<Integer.parseInt(total_record)){
				
				//if(index_start==10000)
				//	break;
				query=hsession.createSQLQuery(sql+condition);
				query.setFirstResult(index_start);
				if(Integer.parseInt(total_record)-index_start<max_record){
					max_record=Integer.parseInt(total_record)-index_start;
				}
				query.setMaxResults(max_record);
				list=query.list();
				
				int record_per_page=60000;
				if(index_start%record_per_page==0){
					
					
					//sheet_main=workbook.createSheet("明细"+(index_start/record_per_page+1),index_start/record_per_page);
					current_filename=filepath+filename+"_"+(index_start/record_per_page+1)+".xls";
					workbook=(new File(current_filename));
					if(workbook.exists()){
						workbook.delete();
					}
					workbook.createNewFile();
					
					bos=new BufferedOutputStream(new FileOutputStream(workbook));
					writer=new OutputStreamWriter(bos,"UTF-8"); 
					
					writer.write("<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
					writer.write("	xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
					writer.write("	xmlns=\"http://www.w3.org/TR/REC-html40\">");
					writer.write("");
					writer.write("	<head>");
					writer.write("	<meta http-equiv=Content-Type content=\"text/html; charset=utf-8\">");
					writer.write("	<meta name=ProgId content=Excel.Sheet>");
					writer.write("	<meta name=Generator content=\"Microsoft Excel 11\">");
					writer.write("");
					writer.write("	<style>");
					writer.write("	<!--table");
					writer.write("		{mso-displayed-decimal-separator:\"\\.\";");
					writer.write("		mso-displayed-thousand-separator:\"\\,\";}");
					writer.write("	@page");
					writer.write("		{margin:1.0in .75in 1.0in .75in;");
					writer.write("		mso-header-margin:.5in;");
					writer.write("		mso-footer-margin:.5in;}");
					writer.write("	tr");
					writer.write("		{mso-height-source:auto;");
					writer.write("		mso-ruby-visibility:none;}");
					writer.write("	col");
					writer.write("		{mso-width-source:auto;");
					writer.write("		mso-ruby-visibility:none;}");
					writer.write("	br");
					writer.write("		{mso-data-placement:same-cell;}");
					writer.write("	.style0");
					writer.write("		{mso-number-format:General;");
					writer.write("		text-align:general;");
					writer.write("		vertical-align:bottom;");
					writer.write("		white-space:nowrap;");
					writer.write("		mso-rotate:0;");
					writer.write("		mso-background-source:auto;");
					writer.write("		mso-pattern:auto;");
					writer.write("		color:windowtext;");
					writer.write("		font-size:10.0pt;");
					writer.write("		font-weight:400;");
					writer.write("		font-style:normal;");
					writer.write("		text-decoration:none;");
					writer.write("		font-family:Arial, sans-serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		border:none;");
					writer.write("		mso-protection:locked visible;");
					writer.write("		mso-style-name:常规;");
					writer.write("		mso-style-id:0;}");
					writer.write("	td");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		padding-top:1px;");
					writer.write("		padding-right:1px;");
					writer.write("		padding-left:1px;");
					writer.write("		mso-ignore:padding;");
					writer.write("		color:windowtext;");
					writer.write("		font-size:10.0pt;");
					writer.write("		font-weight:400;");
					writer.write("		font-style:normal;");
					writer.write("		text-decoration:none;");
					writer.write("		font-family:Arial, sans-serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		mso-number-format:General;");
					writer.write("		text-align:general;");
					writer.write("		vertical-align:bottom;");
					writer.write("		border:none;");
					writer.write("		mso-background-source:auto;");
					writer.write("		mso-pattern:auto;");
					writer.write("		mso-protection:locked visible;");
					writer.write("		white-space:nowrap;");
					writer.write("		mso-rotate:0;}");
					writer.write("	.xl24");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		font-size:12.0pt;");
					writer.write("		font-weight:700;");
					writer.write("		font-family:\"Times New Roman\", serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		text-align:center;");
					writer.write("		vertical-align:middle;");
					writer.write("		border:.5pt solid black;}");
					writer.write("	.xl25");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		font-size:11.0pt;");
					writer.write("		font-family:\"Times New Roman\", serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		text-align:center;");
					writer.write("		vertical-align:middle;");
					writer.write("		border:.5pt solid black;}");
					writer.write("	.xl26");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		font-size:11.0pt;");
					writer.write("		font-family:\"Times New Roman\", serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		text-align:center;");
					writer.write("		vertical-align:middle;");
					writer.write("		border-top:.5pt solid black;");
					writer.write("		border-right:none;");
					writer.write("		border-bottom:.5pt solid black;");
					writer.write("		border-left:.5pt solid black;}");
					writer.write("	.xl27");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		font-size:11.0pt;");
					writer.write("		font-family:\"Times New Roman\", serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		text-align:center;");
					writer.write("		vertical-align:middle;");
					writer.write("		border-top:.5pt solid black;");
					writer.write("		border-right:none;");
					writer.write("		border-bottom:.5pt solid black;");
					writer.write("		border-left:none;}");
					writer.write("	.xl28");
					writer.write("		{mso-style-parent:style0;");
					writer.write("		font-size:11.0pt;");
					writer.write("		font-family:\"Times New Roman\", serif;");
					writer.write("		mso-font-charset:0;");
					writer.write("		text-align:center;");
					writer.write("		vertical-align:middle;");
					writer.write("		border-top:.5pt solid black;");
					writer.write("		border-right:.5pt solid black;");
					writer.write("		border-bottom:.5pt solid black;");
					writer.write("		border-left:none;}");
					writer.write("	ruby");
					writer.write("		{ruby-align:left;}");
					writer.write("	rt");
					writer.write("		{color:windowtext;");
					writer.write("		font-size:9.0pt;");
					writer.write("		font-weight:400;");
					writer.write("		font-style:normal;");
					writer.write("		text-decoration:none;");
					writer.write("		font-family:宋体;");
					writer.write("		mso-generic-font-family:auto;");
					writer.write("		mso-font-charset:134;");
					writer.write("		mso-char-type:none;");
					writer.write("		display:none;}");
					writer.write("	-->");
					writer.write("	</style>");
					writer.write("	<!--[if gte mso 9]><xml>");
					writer.write("	 <x:ExcelWorkbook>");
					writer.write("	  <x:ExcelWorksheets>");
					writer.write("	   <x:ExcelWorksheet>");
					writer.write("	    <x:Name>明细</x:Name>");
					writer.write("	    <x:WorksheetOptions>");
					writer.write("	     <x:Print>");
					writer.write("	      <x:FitWidth>0</x:FitWidth>");
					writer.write("	      <x:FitHeight>0</x:FitHeight>");
					writer.write("	      <x:ValidPrinterInfo/>");
					writer.write("	      <x:PaperSizeIndex>9</x:PaperSizeIndex>");
					writer.write("	      <x:Scale>0</x:Scale>");
					writer.write("	      <x:HorizontalResolution>300</x:HorizontalResolution>");
					writer.write("	      <x:VerticalResolution>300</x:VerticalResolution>");
					writer.write("	     </x:Print>");
					writer.write("	     <x:Selected/>");
					writer.write("	     <x:ProtectContents>False</x:ProtectContents>");
					writer.write("	     <x:ProtectObjects>False</x:ProtectObjects>");
					writer.write("	     <x:ProtectScenarios>False</x:ProtectScenarios>");
					writer.write("	    </x:WorksheetOptions>");
					writer.write("	   </x:ExcelWorksheet>");
					writer.write("	  </x:ExcelWorksheets>");
					writer.write("	  <x:WindowHeight>9150</x:WindowHeight>");
					writer.write("	  <x:WindowWidth>14940</x:WindowWidth>");
					writer.write("	  <x:WindowTopX>360</x:WindowTopX>");
					writer.write("	  <x:WindowTopY>270</x:WindowTopY>");
					writer.write("	  <x:AcceptLabelsInFormulas/>");
					writer.write("	  <x:ProtectStructure>False</x:ProtectStructure>");
					writer.write("	  <x:ProtectWindows>False</x:ProtectWindows>");
					writer.write("	 </x:ExcelWorkbook>");
					writer.write("	</xml><![endif]-->");
					writer.write("	</head>");
					writer.write("");
					writer.write("	<body link=blue vlink=purple>");
					writer.write("");
					writer.write("	<table x:str border=0 cellpadding=0 cellspacing=0 width=1134 style='border-collapse:");
					writer.write("	 collapse;table-layout:fixed;width:853pt'>");
					writer.write("	 <col width=98 style='mso-width-source:userset;mso-width-alt:3584;width:74pt'>");
					writer.write("	 <col width=91 style='mso-width-source:userset;mso-width-alt:3328;width:68pt'>");
					writer.write("	 <col width=126 style='mso-width-source:userset;mso-width-alt:4608;width:95pt'>");
					writer.write("	 <col width=42 style='mso-width-source:userset;mso-width-alt:1536;width:32pt'>");
					writer.write("	 <col width=56 style='mso-width-source:userset;mso-width-alt:2048;width:42pt'>");
					writer.write("	 <col width=147 style='mso-width-source:userset;mso-width-alt:5376;width:110pt'>");
					writer.write("	 <col width=84 style='mso-width-source:userset;mso-width-alt:3072;width:63pt'>");
					writer.write("	 <col width=70 style='mso-width-source:userset;mso-width-alt:2560;width:53pt'>");
					writer.write("	 <col width=140 span=2 style='mso-width-source:userset;mso-width-alt:5120;");
					writer.write("	 width:105pt'>");
					writer.write("	 <col width=70 span=2 style='mso-width-source:userset;mso-width-alt:2560;");
					writer.write("	 width:53pt'>");
					writer.write("	 <tr height=21 style='height:15.75pt'>");
					writer.write("	  <td height=21 class=xl24 width=98 style='height:15.75pt;width:74pt'>企业名称</td>");
					writer.write("	  <td class=xl24 width=91 style='border-left:none;width:68pt'>父企业名称</td>");
					writer.write("	  <td class=xl24 width=126 style='border-left:none;width:95pt'>电话</td>");
					writer.write("	  <td class=xl24 width=42 style='border-left:none;width:32pt'>地址</td>");
					writer.write("	  <td class=xl24 width=56 style='border-left:none;width:42pt'>行业编码</td>");
					writer.write("	  <td class=xl24 width=147 style='border-left:none;width:110pt'>行业名称</td>");
					writer.write("	  <td class=xl24 width=84 style='border-left:none;width:63pt'>所在城市</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>网址</td>");
					writer.write("	  <td class=xl24 width=140 style='border-left:none;width:105pt'>电子邮件</td>");
					writer.write("	  <td class=xl24 width=140 style='border-left:none;width:105pt'>联系人</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>联系电话</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>传真号码</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>所在社区</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>企业介绍信息</td>");
					writer.write("	  <td class=xl24 width=70 style='border-left:none;width:53pt'>别名</td>");
					writer.write("	 </tr>");
					
					i=1;
				}
				
				Iterator it=list.iterator();
				while(it.hasNext()){
					obj=(Object[])it.next();
					writer.write("<tr height=20 style='height:15.0pt'>");
					writer.write("<td height=20 class=xl25 style='height:15.0pt;border-top:none'>"+(String)(obj[0]==null?"":obj[0])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[1]==null?"":obj[1])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[2]==null?"":obj[2])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[3]==null?"":obj[3])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[4]==null?"":obj[4])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[5]==null?"":obj[5])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[6]==null?"":obj[6])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[7]==null?"":obj[7])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[8]==null?"":obj[8])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[9]==null?"":obj[9])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[10]==null?"":obj[10])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[11]==null?"":obj[11])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[12]==null?"":obj[12])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[13]==null?"":obj[13])+"</td>");
					writer.write("<td class=xl25 style='border-top:none;border-left:none'>"+(String)(obj[14]==null?"":obj[14])+"</td>");
					
					writer.write("</tr>");
					
					writer.flush();
					i++;
				}
				index_start=index_start+max_record;
				
				if(index_start%record_per_page==0||index_start==Integer.parseInt(total_record)){
					
					writer.write("</table>");
					writer.write("</body>");
					writer.write("</html>");
					writer.flush();
					writer.close();
				}
			}
		
		}catch(Exception e){
			log.info("生成文件出错",e);
		}
	}
}

 

还是把代码贡献出来吧。藏着掖着,自己也是不会进步滴...原来的Excel设置的格式是提供给其他系统使用的,所以格式需要使用者自己调整。每个文件6w条记录,超过6w条将创建一个新文件。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics