项目在日食但不导出时
问题描述:
我写了一个应用程序,它使用GraphViz根据DOT语法生成一些图表作为.gif。当我从Eclipse运行时,图像生成的很好,但是当我将它作为jar导出时,图像被创建,但是它们中没有数据。当我在Microsoft Picture Viewer中查看它时,它只是一个红色的X.项目在日食但不导出时
它是作为导出的jar工作的,直到我将图片生成放到它自己的线程中。我似乎无法弄清楚这里发生了什么。导出多线程项目时是否有任何问题?有人有主意吗?
谢谢
这是一些代码。很难指出发生了什么问题。
/**
* Writes the graph's image in a file.
* @param img A byte array containing the image of the graph.
* @param to A File object to where we want to write.
* @return Success: 1, Failure: -1
*/
public int writeGraphToFile(byte[] img, File to)
{
try {
FileOutputStream fos = new FileOutputStream(to);
fos.write(img);
fos.close();
} catch (java.io.IOException ioe) { return -1; }
return 1;
}
上述函数是通过此调用从备用线程调用的。
public void generateMainGraph() {
//create the graph and put it to file name mainGraphCount.gif
GraphViz gv = new GraphViz();
System.out.println("Generating MAIN graph...");
//add the ending } to mainDot
mainDot += "}";
File newGraph = new File("graphs\\main" + Integer.toString(mainGraphCount) + ".gif");
gv.writeGraphToFile(gv.getGraph(mainDot), newGraph);
}
这是调用generateMainGraph(...)调用函数的线程。
graphGeneratingThread = new Runnable() {
//This method will run in the timer thread
public void run() {
try {
//Generate the graphs
if (iData.importDataSet()) {
int timeout = 0;
Scanner scan = new Scanner(graphGen.logSource);
while(timeout < 10) {
if(!scan.hasNextLine()) {
Thread.sleep(1000);
timeout++;
} else {
timeout = 0;
graphGen.generateGraph(scan.nextLine()); //This function calls generateMainGraph(...)
if(!beginningButton.isEnabled()) {
enableTivoButtons();
}
}
}
}
} catch(Exception exc) {
System.err.println("GraphGenerationThread Runnable Error: " + exc.getMessage() + "\n");
exc.printStackTrace();
System.exit(1);
}
}
};
答
如果一个项目是多线程的,或者在导出项目时没有区别。差异是由虚拟机如何调度线程引起的(这可能会受到在eclipse中运行的影响)。
由于你的问题是与线程版本,我猜你有内部对象状态正在由另一个线程操作一个线程的中间被损坏。例如:
- 线程A生成图像数据
- 线程B替换一个空
- 线程A的数据阵列写入数据(现在是来自步骤2空)
这将是一个0字节图像的解释。另外一种情况:
- 线程A开始产生图像数据
- 线程B开始生成图像数据
- 线程A完成生成数据。
- 线程A写入图像数据(它现在包含线程B的数据的一部分)
这将是一个腐败的图像文件的原因。调试并发代码可能会非常棘手。我的建议是:
- 查找可以由多个线程一次调用的任何代码。
- 添加日志语句,包括Thread.currentThread()。getName()(如果它不是您正在使用的日志API的一部分)。
- 看看这两个线程的交错,这应该让你知道哪里的数据可能会损坏。
如果您在查找可以一次运行多个线程并影响数据的代码之后寻找“简单解决方案”,只需使该方法同步即可,但这可能会使您尝试的方法失败实现添加线程。
请发布一些**相关**代码供我们查看。 – jjnguy 2010-06-09 16:39:16
添加了上面的代码 – Mike 2010-06-09 18:14:16