目前我有一个像这样的SwingWorker进程的实现。请注意,这些不是实际代码。只是骷髅。
private void jButtonSomeButton ( .... ) {
.....
for( File file: files){
worker( args1, args2 );
}
}
private void worker( args1, args2 ){
mytask = new SwingWorker<Object, Object>(){
public Object doInBackground(){
while( !isCancelled() ){
individualtask( args1, args2 );
}
}
.....
}
}
private void individualtask(args1, args2){
...
table.addRow( somevector ); //add some data to row
...
}
虽然我已经完成了上述工作,但我发现有时行数据会出错。有些人物可能会丢失等等。有时他们没事。我相信我需要一些同步机制,但我没有这方面的经验。你能帮忙建议改进上面的代码吗?感谢
答案 0 :(得分:5)
请注意,doInBackground()方法中的代码在Event Dispatch Thread (EDT)之外运行。然后在其中调用individualTask(args1, args2)
并因此调用table.addRow(...)
在概念上是错误的。更不用说JTable API中不存在addRow(...)
而是DefaultTableModel。{/ p>
繁重的任务必须在doInBackground()
线程中运行,并且必须在EDT中执行Swing组件更新。
正确的方法是使用publish()和process()方法,如Tasks that Have Interim Results课程的Concurrency in Swing部分所述。
说过我建议你也重新考虑这一部分:
private void jButtonSomeButton ( ... ) {
...
for( File file: files){
worker( args1, args2 );
}
}
如果您触发多个更新同一个表的工作人员,那么结果也不会是预期的。当然,这完全取决于你需要达到的并行度水平。
基于此评论:
我必须处理目录中的文件,但我不想连续进行。这就是我使用worker()的原因。你怎么建议我这样做?
在这种情况下,使用SwingWorker
肯定是正确的选择。但请考虑这种情况:
假设目录中有两个文件,即文件A和B.如果触发两个不同的工作程序来处理A和B,那么将有两个并行任务更新同一个表。因此,行将非常异步地添加到表中,您可以从文件A解析行0,1,2,4,7,从文件B解析行3,5,6,8。如果订单在哪些行上被添加到表中,最重要的是解析这些文件的文件并不重要,那么方法就没问题了。
另一方面,如果要首先添加从文件A解析的所有行,然后再添加从文件B解析的所有行,请考虑将此for (File file : files)
循环放在doInBackground()
内。这将确保文件处理和表更新之间的并行性,但要遵守文件处理的顺序。例如:
SwingWorker<Void, Vector> worker = new SwingWorker<Void, Vector>() {
@Override
protected Void doInBackground() {
int numberOfFiles = files.size(); // or files.length if it's an array
int processed = 0;
for (File file : files) {
...
// process each file here and then publish interim results
publish(vector);
...
int progress = (int)(++processed * 100 / numberOfFiles);
setProgress(progress);
}
return null;
}
@Override
protected void process(List<Vector> rows) {
DefaultTableModel model = (DefaultTableModel)table.getModel();
for (Vector row: rows) {
model.addRow(row);
}
}
};
答案 1 :(得分:4)
您不应该从table.addRow()
致电individualTask
。
您可以在doInBackground
中执行后台任务,然后在publish
中执行结果。
请参阅:
http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html