java poi workbook 创建很慢_Java基础(二)和JVM

339534a8c981b1a2aac5b21cbb25a01b.png

一、学习内容

1.Java文件读写

1) Java IO流类图

基于字节的I/O操作

4373386ab9b4ae02383311a77d1576e5.png

0562da39436487863370b3f7632f536e.png

基于字符的I/O操作

e4e2996a0ab3672579695b694e3e3603.png

fb04d138db793e5b252ed62708643338.png

2) 文件读写的几种方式及简单示例

//几种读取文件的方式
//方式1
//读取文件 字节流
InputStream inputStream = new FileInputStream("f:zhangqiao1.txt");
//写入相应的文件
OutputStream outputStream = new FileOutputStream("f:zhangqiao2.txt");
//一次性取多少字节
byte[] bytes = new byte[2048];
//接受读取的内容
int n = -1;
//循环取出数据
while ((n = inputStream.read(bytes,0,bytes.length)) != -1){
String str = new String(bytes,0,n,"GBK");
System.out.println(str);
outputStream.write(bytes,0,n);
}
inputStream.close();
outputStream.close();
//方式2
//读取文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("f:zhangqiao1.txt"));
//写入相应的文件
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("f:zhangqiao2.txt"));
//读取数据
//一次性取出多少字节
byte[] bytes1 = new byte[2048];
//接受读取的内容
int n1 = -1;
//循环取出数据
while ((n1 = bufferedInputStream.read(bytes1,0,bytes1.length)) != -1){
//转换成字符串
String str1 = new String(bytes1,0,n1,"GBK");
System.out.println(str1);
bufferedOutputStream.write(bytes1,0,n1);
}
//清除缓存
bufferedOutputStream.flush();
//关闭流
bufferedInputStream.close();
bufferedOutputStream.close();
//方式3
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("f:zhangqiao1.txt"),"GBK");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("f:zhangqiao2.txt"),"GBK");
char[] data = new char[1024];
int n2 = -1;
while ((n2 = inputStreamReader.read(data)) != -1){
String str2 = new String(data,0,n2);
System.out.println(str2);
outputStreamWriter.write(str2);
}
outputStreamWriter.flush();
inputStreamReader.close();
outputStreamWriter.close();
//方式4 字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("f:zhangqiao1.txt"),"GBK"));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("f:zhangqiao2.txt"),"GBK"));
String str3 = null;
while ((str3 = bufferedReader.readLine()) != null){
System.out.println(str3);
bufferedWriter.write(str3);
bufferedWriter.newLine();
}
bufferedWriter.flush();
bufferedReader.close();
bufferedWriter.close();
//方式五
Reader reader = new InputStreamReader(new FileInputStream("f:zhangqiao1.txt"),"GBK");
PrintWriter printWriter = new PrintWriter(new FileWriter("f:zhangqiao2.txt"));
char[] data1 = new char[1024];
int n3 = -1;
while ((n3 = reader.read(data1)) != -1){
String str2 = new String(data1,0,n3);
System.out.println(str2);
printWriter.write(str2);
}
printWriter.flush();
printWriter.close();
reader.close();

3) Java操作Excel表格

操作表格的两种方式jxl和poi

l jxl

使用jxl写Excel

/**
* jxl写Excel jxl目前不支持xlsx格式的文件
* */
File file = new File("f:jxlDemo.xls");
//创建工作簿
WritableWorkbook workbook = Workbook.createWorkbook(file);
//创建一个工作表
WritableSheet writableSheet = workbook.createSheet("sheet1",0);
for(int row = 0;row < 10;row++){
for(int col = 0;col < 10;col++){
writableSheet.addCell(new Label(col,row,"data"+row+col));
}
}
//向工作表中添加数据
workbook.write();
workbook.close();

使用jxl读Excel

/**
* jxl读Excel
* */
File file1 = new File("f:jxlDemo.xls");
//获得工作簿对象
Workbook workbook1 = Workbook.getWorkbook(file1);
//获得所有工作表
Sheet[] sheets = workbook1.getSheets();
if(sheets != null){
for (Sheet sheet:sheets) {
int rows = sheet.getRows();
int cols = sheet.getColumns();
for(int col = 0;col < cols;col++){
for(int row = 0;row < rows;row++){
System.out.printf("%10s",sheet.getCell(col,row).getContents());
}
System.out.println();
}
}
}
workbook1.close();

l poi

使用poi写Excel

/**
* poi写Excel
* @param pathName 文件路径
* @param sheetName 表格的名称
* @param style 表格的格式
* @param titles 表头信息
* @param datas 表格信息
* */
public static void writeExcel(String pathName, String sheetName, String style, List<String> titles,List<String> datas)
throws Exception{
Workbook workbook;
if(".XLS".equals(style.toUpperCase())){
workbook = new HSSFWorkbook();
}else {
workbook = new XSSFWorkbook();
}
Sheet sheet = workbook.createSheet(sheetName);
Row row = sheet.createRow(0);
//创建表头信息
for(int i = 0;i < titles.size();i++){
Cell cell = row.createCell(i);
cell.setCellValue(titles.get(i));
}
//创建表格信息
int index = 0;
while (index < 5){
index++;
row = sheet.createRow(index);
for(int i = 0;i < 5;i++){
Cell cell = row.createCell(i);
cell.setCellValue("hello");
}
}
/*
* 写入到文件中*/
File file = new File(pathName);
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
workbook.write(outputStream);
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(null != outputStream){
outputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}

使用poi读Excel

/**
* poi读Excel
* */
public static void readExcel(String pathName) throws IOException {
File file = new File(pathName);
FileInputStream fileInputStream = new FileInputStream(file.getAbsoluteFile());
HSSFWorkbook hssfWorkbook = null;
XSSFWorkbook xssfWorkbook = null;
Sheet sheet = null;
//indexOf(String str)返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
xssfWorkbook = new XSSFWorkbook(fileInputStream);
sheet = xssfWorkbook.getSheetAt(0);
int firstRowNum = sheet.getFirstRowNum();
int lastRowNum = sheet.getLastRowNum();
String first = "";
String second = "";
for(int i = firstRowNum;i <= lastRowNum;i++){
Row row = sheet.getRow(i);
if(row != null){
if(row.getCell(0) != null){
row.getCell(0).setCellType(CellType.STRING);
first = row.getCell(0).getStringCellValue();
}
if(row.getCell(1) != null){
row.getCell(1).setCellType(CellType.STRING);
second = row.getCell(1).getStringCellValue();
}
}
System.out.println("第" + i + "行信息为:" + first + " | " + second);
}
}

2.JVM

1) JVM使得Java具有跨平台性

.java源文件通过编译器编译成.class字节码文件,JVM加载并运行.class字节码文件。在Windows系统上运行,则通Windows上的JVM进行解释,而在Linux系统上,则通过Linux上的Jvm解释执行。所以Java跨平台,需要保证有相匹配的JVM,如果没有,则不能进行跨平台。

474319282c8c94084d3b9c65fa7a1261.png

2) Java运行时区域

74cbc771c6daccef30dd58c538bd727f.png

l 程序计数器:指向当前线程正在执行的字节码指令。

l 虚拟机栈:虚拟机栈是Java执行方法的内存模型,每个方法执行的时候都会创建一个栈帧,把栈帧压入栈,当方法正常返回或者抛出未捕获的异常的时候,栈帧都会出栈。

栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接

a) 局部变量表:包含了方法执行过程中的所有变量。局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部数组的大小

b) 返回值:如果有返回值,压入调用者栈帧中的操作数栈中,并且把PC的值指向方法调用指令后面的一条指令地址

c) 操作数栈:操作变量的内存模型。操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stack项中)。操作数栈的元素可以是任意Java类型,包括long和double,32位数据占用栈空间为1 ,64位数据占用2。

d) 动态链接:每个栈帧都持有在运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接。

线程私有

l 本地方法栈(线程独享

调用本地native的内存模型

方法区(线程共享):用来存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据

l 堆:java对象存储的地方

Java堆是虚拟机管理的内存中最大的一块

Java堆是所有线程共享的区域

在虚拟机启动时创建

在内存区域的唯一目的就是存放对象实例,几乎所有对象实例都在这里分配内存,存放new生成的对象和数组

Java堆是垃圾收集器管理的内存区域,很多时候称为“GC堆”

3) jdk1.8,堆的内存划分

89e9586653244685e431f5352f000ece.png

其中最上一层是Sursery内存,一个对象被创建以后首先被放到Sursery中的Eden内存中,如果存活期超两个Survivor之后就会被转移Old Generation中,永久内存中存放着对象的方法、变量等元数据信息。通过如果永久内存不够,我们就会得到如下错误:java.lang.OutOfMemoryError: PermGen,而因为 JDK8中把存放元数据中的永久内存从堆内存中移到了本地内存(native memory)中,一般情况下你都不会得到这个错误,它可以通过自动增长来避免JDK7以及前期版本中常见的永久内存错误。

4) 常见的垃圾回收方法

l 标记清除(Mark-Sweep)

l 复制清除(Copying)

l 标记-整理(Mark-Compact)

l 分代收集算法(大部分JVM垃圾收集器采用此方法)

5) 几种不同的垃圾回收类型

l Minor GC:从年轻代回收内存

l Major GC:当eden区内存不足时出发,清理整个老年代

l Full GC:清理整个堆空间,包括年轻代和老年代,当老年代内存不足时触发

6) jvm优化

a) 一般来说,当survivor区不够大或者占用量达到50%,就会把一些对象放到老年区。通过设置合理的eden区,survivor区及使用率,可以将年轻对象保存在年轻代,从而避免full GC,使用-Xmn设置年轻代的大小

b) 对于占用内存比较多的大对象,一般会选择在老年代分配内存。如果在年轻代给大对象分配内存,年轻代内存不够了,就要在eden区移动大量对象到老年代,然后这些移动的对象可能很快消亡,因此导致full GC。通过设置参数:-XX:PetenureSizeThreshold=1000000,单位为B,标明对象大小超过1M时,在老年代(tenured)分配内存空间。

c) 一般情况下,年轻对象放在eden区,当第一次GC后,如果对象还存活,放到survivor区,此后,每GC一次,年龄增加1,当对象的年龄达到阈值,就被放到tenured老年区。这个阈值可以同构-XX:MaxTenuringThreshold设置。如果想让对象留在年轻代,可以设置比较大的阈值。

d) 设置最小堆和最大堆:-Xmx和-Xms稳定的堆大小对垃圾回收是有利的,获得一个稳定的堆大小的方法是设置-Xms和-Xmx的值。这样设置,系统在运行时堆大小理论上是恒定的,稳定的堆空间可以减少GC次数,因此,很多服务端都会将这两个参数设置为一样的数值。稳定的堆大小虽然减少GC次数,但是增加每次GC的时间,因为每次GC要把堆的大小维持在一个区间内。

e) 一个不稳定的堆并非毫无用处。在系统不需要使用大内存的时候,压缩堆空间,使得GC每次应对一个较小的堆空间,加快单次GC次数。基于这种考虑,JVM提供两个参数,用于压缩和扩展堆空间。
(1)-XX:MinHeapFreeRatio 参数用于设置堆空间的最小空闲比率。默认值是40,当堆空间的空闲内存比率小于40,JVM便会扩展堆空间
(2)-XX:MaxHeapFreeRatio 参数用于设置堆空间的最大空闲比率。默认值是70, 当堆空间的空闲内存比率大于70,JVM便会压缩堆空间。
(3)当-Xmx和-Xmx相等时,上面两个参数无效

f) 通过增大吞吐量提高系统性能,可以通过设置并行垃圾回收收集器。
(1)-XX:+UseParallelGC:年轻代使用并行垃圾回收收集器。这是一个关注吞吐量的收集器,可以尽可能的减少垃圾回收时间。
(2)-XX:+UseParallelOldGC:设置老年代使用并行垃圾回收收集器。

g) 尝试使用大的内存分页:使用大的内存分页增加CPU的内存寻址能力,从而系统的性能。-XX:+LargePageSizeInBytes 设置内存页的大小

h) 使用非占用的垃圾收集器。-XX:+UseConcMarkSweepGC老年代使用CMS收集器降低停顿。

i) -XXSurvivorRatio=3,表示年轻代中的分配比率:survivor:eden = 2:3

7) jvm性能调优工具

l Java Process Status(jps):输出JVM中运行的进程状态信息

l jstack:查看java进程内线程的堆栈信息

l jmap:用于生成堆转存快照

l jhat:用于分析jmap生成的堆转存快照

l jstat是JVM统计监测工具,可用来显示垃圾回收信息、类加载信息、新生代统计信息

l VisualVM:故障处理工具

8) jvm参数在哪里设置

a) 集成开发环境下启动并使用JVM,如eclipse需要修改根目录文件eclipse.ini;

b) Windows服务器下安装版Tomcat,可使用Tomcat7w.exe工具(tomcat目录下)和直接修改注册表两种方式修改Jvm参数;

c) Windows服务器解压版Tomcat注册Windows服务,方法同上;

d) 解压版本的Tomcat, 通过startup.bat启动tomcat加载配置的,在tomcat 的bin 下catalina.bat 文件内添加;

e) Linux服务器Tomcat设置JVM,修改TOMCAT_HOME/bin/catalina.sh;

二、存在的问题

对于JVM的优化方案因为缺乏实际经验不能彻底理解,包括调优工具也没有实际使用过

三、明天学习计划

Mysql多表联查语句

框架相关(Spring,Springboot,Mybatis)


版权声明:本文为weixin_42191480原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。