【发布时间】:2023-08-28 10:35:01
【问题描述】:
我在SwingWorker 中遇到了一个奇怪的问题(无论如何对我来说很奇怪),我用它来将另一个“SwingWorker”线程的结果保存为制表符分隔的文件(只是一个数据电子表格)。
这里是工人,它初始化并声明一个对象,该对象组织数据并将每个表行写入文件(使用BufferedWriter):
// Some instance variables outside of the SwingWorker:
// model: holds a matrix of numerical data (double[][])
// view: the GUI class
class SaveWorker extends SwingWorker<Void, Void> {
/* The finished reordered matrix axes */
private String[] reorderedRows;
private String[] reorderedCols;
private String filePath; // the path of the file that will be generated
public SaveWorker(String[] reorderedRows, String[] reorderedCols) {
// variables have been checked for null outside of the worker
this.reorderedRows = reorderedRows;
this.reorderedCols = reorderedCols;
}
@Override
protected Void doInBackground() throws Exception {
if (!isCancelled()) {
LogBuffer.println("Initializing writer.");
final CDTGenerator cdtGen = new CDTGenerator(
model, view, reorderedRows, reorderedCols);
LogBuffer.println("Generating CDT.");
cdtGen.generateCDT();
LogBuffer.println("Setting file path.");
filePath = cdtGen.getFilePath(); // stops inside here, jumps to done()
LogBuffer.println("Path: " + filePath);
}
return null;
}
@Override
protected void done() {
if (!isCancelled()) {
view.setLoadText("Done!");
LogBuffer.println("Done saving. Opening file now.");
// need filePath here to load and then display generated file
visualizeData(filePath);
} else {
view.setReorderOngoing(false);
LogBuffer.println("Reordering has been cancelled.");
}
}
}
当我从 Eclipse 运行程序时,一切正常。没有任何问题。现在我知道这里有很多关于 Eclipse 运行良好而可运行 JAR 失败的问题。这通常是由于不包括依赖项或以错误的方式引用它们。但奇怪的是 JAR also 在从命令行启动时完全可以正常工作(Windows 8.1):
java -jar reorder.jar
等等,一切都符合预期。 CDTGenerator 将完成,将所有矩阵行写入文件,并返回 filePath。使用filePath,我随后可以打开新文件并显示矩阵。
如果双击桌面上的 JAR(我在 Eclipse 中创建它时放置它的位置),程序会在此通知我发生的事情。我收到了我为filePath == null 的情况创建的错误消息,并使用一些日志记录关闭了CDTGenerator 对象停止执行其方法generateCDT() 的位置(Eclipse 调试器也不会重现错误并按计划执行所有操作)。
日志显示的内容让我认为这是并发问题,但实际上我反对这一点,因为 Eclipse 和 命令行都可以正常运行代码。日志只是告诉我,代码在循环期间突然停止执行,该循环将double 值从矩阵行 (double[]) 转换为 Strings 以存储在 String[] 中,以便以后使用 BufferedWriter 编写。
如果我在该循环中使用更多日志记录,则循环将在不同的迭代器 (???) 处停止。
此外,代码确实适用于小矩阵 (130x130),但不适用于较大的矩阵 (1500x3500),但我尚未测试限制在哪里。这使它看起来几乎是时间相关的,或记忆。
我还使用 jVisualVM 来查看潜在的内存问题,但即使对于较大的矩阵,我的内存约为 250MB,这对于潜在的OutOfMemoryExceptions 来说几乎没有问题。
最后,我能想到的最后一个潜在因素:由于一些classpath 问题(清理和重建没有效果......)而生成 JAR '失败',但这从来都不是我之前遇到的问题使用“损坏的”JAR 多次运行代码并从桌面执行。
我是一个真正的编程新手,所以如果可能的话,请指出一些方向。我试图找到记录的异常,记录变量的值,我正在检查它停止执行的数组中的null 和IndexOutOfBound 问题......我完全不知所措尤其是因为这从命令行运行良好。
【问题讨论】:
-
拜托,你能发布你的错误的堆栈跟踪吗?如果您在可视化它时遇到任何问题,请尝试配置一些记录器以便将其转储到文件中,但完整的跟踪将非常有用
-
这正是我的问题。 no 堆栈跟踪,甚至在命令提示符中也没有,因为从那里启动时它工作正常。将行写入文件的方法只是随机停止,在一个特定循环的不同点,这取决于我打印了多少日志消息(再次,让我认为时间是一个因素)。没有循环迭代器越界,没有数组值
null在那个循环中...... -
当程序停止时,进行线程转储并查看是否存在死锁,或者应该处于可运行状态的线程是否由于某种原因(阻塞、等待、timed_waiting)或完全不存在。
-
顺便看看您的操作系统文件关联和执行它们的预定程序。你确定你在命令行和双击它都使用相同的java版本吗?
-
这可能是它。我注意到别的东西:尝试在 jVisualVM 中进行线程转储只能从命令行进行。否则“线程”选项卡甚至不会出现,也不允许我在“监视器”选项卡中进行 GC 转储。我马上回来报告。
标签: java concurrency jar io swingworker