所以我用Java编写了一个大型的素数生成器(在JavaFX的帮助下)。
它使用Apache POI库(我相信我使用的是v3.17)将结果输出到Excel电子表格。
此导出逻辑的静态方法保存在名为ExcelWriter的类中。基本上,它遍历Arraylist参数并用它的内容填充XSSFWorkbook。后来,FileOutputStream用于实际使其成为excel文件。以下是相关部分:
public class ExcelWriter {
//Configured JFileChooser to make alert before overwriting old files
private static JFileChooser fileManager = new JFileChooser(){
@Override
public void approveSelection(){
...
}
};
private static FileFilter filter = new FileNameExtensionFilter("Excel files","xlsx");
private static boolean hasBeenInitialized = false;
//Only method that can be called externally to access this class's functionality
public static <T extends Object> void makeSpreadsheet
(ArrayList<T> list, spreadsheetTypes type, int max, String title, JFXProgressBar progressBar)
throws IOException, InterruptedException{
progressBar.progressProperty().setValue(0);
switch (type){
case rightToLeftColumnLimit:
makeSpreadsheetRightToLeft(list, false, max, title, progressBar);
break;
...
}
}
static private <T extends Object> void makeSpreadsheetRightToLeft
(ArrayList<T> list, boolean maxRows, int max, String title, JFXProgressBar progressBar)
throws IOException, InterruptedException{
initializeChooser();
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Primus output");
int rowPointer = 0;
int columnPointer = 0;
double progressIncrementValue = 1/(double)list.size();
//Giving the spreadsheet an internal title also
Row row = sheet.createRow(0);
row.createCell(0).setCellValue(title);
row = sheet.createRow(++rowPointer);
//Making the sheet with a max column limit
if (!maxRows){
for (T number: list){
if (columnPointer == max){
columnPointer = 0;
row = sheet.createRow(++rowPointer);
}
Cell cell = row.createCell(columnPointer++);
progressBar.setProgress(progressBar.getProgress() + progressIncrementValue);
cell.setCellValue(number.toString());
}
}else {
//Making the sheet with a max row limit
int columnWrapIndex = (int)Math.ceil(list.size()/(float)max);
for (T number: list){
if (columnPointer == columnWrapIndex){
columnPointer = 0;
row = sheet.createRow(++rowPointer);
}
Cell cell = row.createCell(columnPointer++);
progressBar.setProgress(progressBar.getProgress() + progressIncrementValue);
cell.setCellValue(number.toString());
}
}
writeToExcel(workbook, progressBar);
}
static private void writeToExcel(XSSFWorkbook book, JFXProgressBar progressBar) throws IOException, InterruptedException{
//Exporting to Excel
int returnValue = fileManager.showSaveDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION){
File file = fileManager.getSelectedFile();
//Validation logic here
try{
FileOutputStream out = new FileOutputStream(file);
book.write(out);
out.close();
book.close();
}catch (FileNotFoundException ex){
}
}
}
}
之后,我的FXML文档控制器有一个buttonListerner,它调用:
longCalculationThread thread = new longCalculationThread(threadBundle);
thread.start();
longcalculationthread创建一个包含大约一百万个素数的列表,并使用以下代码将它们导出到ExcelWriter:
private void publishResults() throws IOException, InterruptedException{
if (!longResults.isEmpty()){
if (shouldExport) {
progressText.setText("Exporting to Excel...");
ExcelWriter.makeSpreadsheet(longResults, exportType, excelExportLimit, getTitle(), progressBar);
}
}
问题是,即使在XSSF工作簿中保存工作簿的变量是它所使用的方法的局部变量,它也不会在之后收集垃圾。
它占用了大约1.5GB的RAM(我不知道为什么),并且只在调用另一个大型导出时才重新分配该数据(不适用于小型导出)。 我的问题并不是真的需要占用大量内存,即使方法完成时内存也没有GC。 以下是我的NetBeans配置文件的一些图片:
答案 0 :(得分:0)
我找到了答案!我不得不用System.gc()提示GC。我记得早些时候尝试过这个,但是我必须把它放在工作簿仍然可访问的速度中,因此无法进行GCed。