我的问题是这样的: 即使读取完成(数百万行)的文件后,如何仍能使该线程保持活动状态
问题是我有一个从javafx应用程序线程启动的线程,然后该线程(新线程)对文本文件执行一些读/写操作,当面对巨大的文件以进行解析时,它不会自然退出,需要花费一千七百万具体来说,行大。
我假设这是由于线程保留了我所缺少的某些资源,但是,由于我使用的是try-with-resource模型,所以我不确定这是否真的可能。
这是触发线程的javafx控制器类(使用fxml):
MainController.java:
/**
* This method handles what happens when the calculate button is clicked.
* The main thing this does is disable/enable a few Nodes, as well as sparks
* off the background thread.
*
* @param event
*/
@FXML
private void convert_button_action(ActionEvent event) {
closing_label.setVisible(true);
convert_button.setDisable(true);
input_text = input_NCLocation_field.getText();
output_text = output_Location_Field.getText();
indicator_node.setVisible(true);
if (!toggleSwitch.isSelected()) {
(new Thread(new FileWriter(input_text, output_text, indicator_node))).start();
} else {
DateWriter temp = new DateWriter(input_text, output_text, indicator_node, yr_mn_dy.isSelected());
(new Thread(temp)).start();
}
}
那里没有什么花哨的东西,只是一些使事物可见/不可见,并根据用户的输入启动适当的线程。接下来是整个Thread类,因为它不是太大。它所做的实际上只是将一行看起来像是:yearmonthday转换为year,month,day,或者如果用户单击了要求的复选框,则它将年月和日列分隔为单独的文件。只是用于用例的便捷工具。
请注意run()
方法末尾的println语句。我每次都看到这个println,但是在它发生之后,什么也没有发生。程序不退出,线程不停止,什么也没有。
package File_Conversion;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javafx.application.Platform;
import javafx.scene.control.ProgressIndicator;
/**
* This class is the background 'worker' thread that does all of the heavy duty
* file IO for splitting up the NC file. It periodically sends reports back to
* the main application thread to update the progress indicator.
*
* @author William
*/
public class DateWriter implements Runnable {
private final ProgressIndicator myIndicator;
private static File ncFile;
private final String outputLocationFile;
private float zmax, zmin, xmax, xmin, ymax, ymin;
private ArrayList<Float> xList, yList, zList;
private final DecimalFormat numberFormat = new DecimalFormat("#.000000");
private final DecimalFormat numberFormatMinMax = new DecimalFormat("#.00000");
private final boolean yr_mon_day;
/**
* This is the main constructor, it needs a valid NC file to continue.
*
* @param inputNCFile
* @param outputLocation
* @param myIndicator
* @param yr_mon_day
*/
public DateWriter(String inputNCFile, String outputLocation, ProgressIndicator myIndicator, boolean yr_mon_day) {
this.yr_mon_day = yr_mon_day;
this.myIndicator = myIndicator;
ncFile = new File(inputNCFile);
outputLocationFile = outputLocation;
}
/**
* The primary run() method, starts the thread.
*/
@Override
public void run() {
convertDate();
Platform.runLater(new Runnable() {
@Override
public void run() {
File_Conversion.stage_returner().close();
}
});
System.out.println("I'm at the end of the run...??");
}
public boolean convertDate() {
BufferedReader br = null;
java.io.FileWriter yearWriter = null, MonthWriter = null, DayWriter = null
,fWriter = null;
BufferedWriter yearBuf = null, monthBuf = null, dayBuf = null, writer = null;
try {
br = new BufferedReader(new FileReader(ncFile));
if (yr_mon_day) {
yearWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_year.csv", false);
yearBuf = new BufferedWriter(yearWriter);
MonthWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_month.csv", false);
monthBuf = new BufferedWriter(MonthWriter);
DayWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_day.csv", false);
dayBuf = new BufferedWriter(DayWriter);
String input;
String temp;
String temp2;
String temp3;
while ((input = br.readLine()) != null) {
temp = input.substring(0, 4);
temp2 = input.substring(4, 6);
temp3 = input.substring(6);
Platform.runLater(new Runnable() {
@Override
public void run() {
myIndicator.setProgress(-1);
}
});
yearBuf.write(temp + "\n");
monthBuf.write(temp2 + "\n");
dayBuf.write(temp3 + "\n");
}
} else {
fWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName() + "_modified.csv", false);
writer = new BufferedWriter(fWriter);
String input;
String temp;
while ((input = br.readLine()) != null) {
temp = input.substring(0, 4) + "," + input.substring(4, 6) + "," + input.substring(6);
Platform.runLater(new Runnable() {
@Override
public void run() {
myIndicator.setProgress(-1);
}
});
writer.write(temp + "\n");
}
}
} catch (IOException e) {
e.printStackTrace(System.out);
}finally{
try{
if (br!=null) br.close();
if (yearBuf !=null) yearBuf.close();
if (monthBuf != null)monthBuf.close();
if (dayBuf != null)dayBuf.close();
if (yearWriter != null)yearWriter.close();
if (MonthWriter != null)MonthWriter.close();
if (DayWriter != null)DayWriter.close();
if (fWriter != null) fWriter.close();
if (writer != null) writer.close();
}catch(IOException e){
e.printStackTrace(System.out);
}
}
return true;
}
}
再次,没有什么幻想,有一些缓冲的流和编写器,仅此而已!值得注意的是,这对于小型/非巨型文件非常适用。只有当面对数百万行的文件时,我才能看到这种行为。
您能提供的任何帮助将不胜感激,谢谢!
编辑1
只是为了澄清一下,if /
else的部分原因是尝试资源疯狂,而另一部分则以更传统的方式,仅是为了举例说明已经尝试了两种方法,出现了相同的症状排除了通过两个逻辑块运行的线程,因此我相当确定关闭资源的方式与此无关。
因此,事实证明这是一个解决方案,我对昨天有个想法,但从未采取任何行动。
从本质上讲,我遇到的问题的根源(我认为)是由于写缓冲区溢出导致的,导致未定义的行为。
现在,我不知道这是由于Java bufferedwriter的错误Java实现还是由于到底发生了什么,但是解决方案却变得相对简单:现在
每进行一次迭代就
刷新流,我知道您知道什么在想,加!经常这样!减速一定是巨大的!是的,确实如此,增速放缓是巨大的,它使解析文件的时间从大约14秒缩短到大约4分钟达到了1700万行。
可能我可以稍微提高刷新次数以提高性能,但是每10次刷新一次仍然失败。
我敢肯定,这是Java中如何处理读/写操作和内存管理的内部结果,而且我没有时间去研究它。如果有人想花时间对这种行为做出很好的解释,我会很乐意将我接受的答案切换到他们的帖子,因为它更加完整。
固定类(现在可以使用)的代码以DateWriter
供将来检查:
package File_Conversion;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javafx.application.Platform;
import javafx.scene.control.ProgressIndicator;
/**
* This class is the background 'worker' thread that does all of the heavy duty
* file IO for splitting up the NC file. It periodically sends reports back to
* the main application thread to update the progress indicator.
*
* @author William
*/
public class DateWriter implements Runnable {
private final ProgressIndicator myIndicator;
private static File ncFile;
private final String outputLocationFile;
private float zmax, zmin, xmax, xmin, ymax, ymin;
private ArrayList<Float> xList, yList, zList;
private final DecimalFormat numberFormat = new DecimalFormat("#.000000");
private final DecimalFormat numberFormatMinMax = new DecimalFormat("#.00000");
private final boolean yr_mon_day;
/**
* This is the main constructor, it needs a valid NC file to continue.
*
* @param inputNCFile
* @param outputLocation
* @param myIndicator
* @param yr_mon_day
*/
public DateWriter(String inputNCFile, String outputLocation, ProgressIndicator myIndicator, boolean yr_mon_day) {
this.yr_mon_day = yr_mon_day;
this.myIndicator = myIndicator;
ncFile = new File(inputNCFile);
outputLocationFile = outputLocation;
}
/**
* The primary run() method, starts the thread.
*/
@Override
public void run() {
convertDate();
Platform.runLater(new Runnable() {
@Override
public void run() {
File_Conversion.stage_returner().close();
}
});
System.out.println("At the end of the method.");
}
public boolean convertDate() {
BufferedReader br = null;
java.io.FileWriter yearWriter = null, monthWriter = null, dayWriter = null, fWriter = null;
BufferedWriter yearBuf = null, monthBuf = null, dayBuf = null, writer = null;
try {
br = new BufferedReader(new FileReader(ncFile));
if (yr_mon_day) {
yearWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_year.csv", false);
yearBuf = new BufferedWriter(yearWriter);
monthWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_month.csv", false);
monthBuf = new BufferedWriter(monthWriter);
dayWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_day.csv", false);
dayBuf = new BufferedWriter(dayWriter);
String input;
String temp;
String temp2;
String temp3;
while ((input = br.readLine()) != null) {
temp = input.substring(0, 4);
temp2 = input.substring(4, 6);
temp3 = input.substring(6);
Platform.runLater(new Runnable() {
@Override
public void run() {
myIndicator.setProgress(-1);
}
});
yearBuf.write(temp + "\n");
monthBuf.write(temp2 + "\n");
dayBuf.write(temp3 + "\n");
yearBuf.flush();
monthBuf.flush();
dayBuf.flush();
temp = null;
temp2 = null;
temp3 = null;
}
} else {
fWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName() + "_modified.csv", false);
writer = new BufferedWriter(fWriter);
String input;
String temp;
while ((input = br.readLine()) != null) {
temp = input.substring(0, 4) + "," + input.substring(4, 6) + "," + input.substring(6);
Platform.runLater(new Runnable() {
@Override
public void run() {
myIndicator.setProgress(-1);
}
});
writer.write(temp + "\n");
writer.flush();
}
}
} catch (IOException e) {
e.printStackTrace(System.out);
} finally {
try {
if (br != null) {
br.close();
}
if (yearBuf != null) {
yearBuf.close();
}
if (monthBuf != null) {
monthBuf.close();
}
if (dayBuf != null) {
dayBuf.close();
}
if (yearWriter != null) {
yearWriter.close();
}
if (monthWriter != null) {
monthWriter.close();
}
if (dayWriter != null) {
dayWriter.close();
}
if (fWriter != null) {
fWriter.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace(System.out);
}
}
return true;
}
}
问题内容: 看一下这段代码: 通常,到达的结尾时,程序会终止。但是在此示例中,程序将打印“ main of End”,然后继续运行,因为线程仍在运行。有没有一种方法可以使线程在结束时 自动 停止,而无需使用类似的东西? 问题答案: 您正在创建的线程是独立的,并且不依赖于主线程终止。您可以使用线程。 当没有其他线程在运行时,守护进程线程将由JVM终止,它也包括一个执行主线程。
线程的结束 现有问题 当内核线程终止时,会发生什么?如果就按目前的实现,我们会发现线程所执行的函数末尾会触发 Exception::InstructionPageFault 而终止,其中访问的的地址 stval = 0。 这是因为内核线程在执行完 entry_point 所指向的函数后会返回到 ra 指向的地址,而我们没有为其赋初值(初值为 0)。此时,程序就会尝试跳转到 0x0 地址,而显然它是
我正在我的程序中创建一些线程。这里我使用了join方法,这样主线程就会等待我的所有线程。但是每当我运行这个程序的时候,它并没有完成,所有的信息消息都被打印出来,但是程序仍然没有顺利结束。有没有人能帮我解决这个问题呢? 下面是我的代码: 下面是DeployerThread的代码: 下面是线程转储: “CompilerThread0”后台进程Prio=3 TID=0x002E4310 NID=0x20
我是Vert.x的新手,我试图创建一个简单的下载服务。 当此错误发生时,没有数据通过线路发送,我检查了浏览器和嗅探数据包TCP数据包(0字节从服务器发送到浏览器)。 唯一有效的方法是使用关闭连接,这至少关闭了keep-alive http连接,并结束浏览器请求。 我想要实现的是向客户机发回一些信息,以告知发生了错误,可能将状态代码设置为适当的错误,并可能向其添加一些细节(在状态文本或响应正文中)。
问题内容: 如果我在无限循环中有一个线程,有没有办法在主程序结束时(例如,当我按 +时 )终止它? 问题答案: 检查这个问题。正确答案对如何以正确的方式终止线程有很好的解释: 是否有任何方法可以杀死Python中的线程? 要使线程在键盘中断信号(ctrl + c)上停止,您可以在退出之前捕获异常“ KeyboardInterrupt”并进行清除。像这样: 这样,您可以控制程序突然终止时的处理方式。
问题内容: 我正在运行一个python脚本,它曾经可以运行(现在甚至可以在我的另一台笔记本电脑上运行),但是在我当前的计算机上却不行-我只收到错误代码: 我没有得到任何其他结果-甚至从文件开头的“打印”命令也没有得到。 我还没有找到特定的东西。我重新安装了python(2.7.9),pygame(1.9.1)甚至pycharm(首先尝试4.5,现在使用5.0-相同的结果) 有人知道该错误代码意味着