SwingWorker过程的设计

dor*_*thy 1 java swing swingworker

目前我有一个像这样的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
   ...
}
Run Code Online (Sandbox Code Playgroud)

虽然我已经进行了上述操作,但我发现有时行数据会出错.有些人物可能会丢失等等.有时他们没事.我相信我需要一些同步机制,但我没有这方面的经验.你能帮忙建议改进上面的代码吗?谢谢

dic*_*c19 5

请注意,doInBackground()方法中的代码在Event Dispatch Thread(EDT)之外运行.然后individualTask(args1, args2)在里面调用并因此调用table.addRow(...)在概念上是错误的.更不用说JTable API中addRow(...)不存在,而是DefaultTableModel.

繁重的任务必须在doInBackground()线程中运行,并且必须在EDT中执行Swing组件更新.

正确的方法是使用publish()process()方法,如Swing课程中的" 并发结果"部分中的" 任务"中所述.

话虽如此,我建议你也重新考虑这一部分:

private void jButtonSomeButton ( ... ) {
    ...
    for( File file: files){                   
       worker( args1, args2 );           
    }
}
Run Code Online (Sandbox Code Playgroud)

如果触发多个更新同一个表的worker,那么结果也不会是预期的.当然,这完全取决于您需要达到的并行度水平.


编辑

根据这个评论:

我必须处理目录中的文件,但我不想连续进行.这就是我使用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);
        }
     }
};
Run Code Online (Sandbox Code Playgroud)