繁体   English   中英

如何根据从其他线程中长时间运行的任务收到的​​通知更新JTable?

[英]How do I update a JTable based on a notification received from a long-running task in other thread?

我有一个Observer TableModel,它监听在数据库中执行的一些更改,然后调用下面的更新方法。 我的问题是,我应该如何防止错误:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at com.mysimpatico.memoplatform.persistenceui.MeaningsViewerTopComponent$DefaultTableModelImpl.update(MeaningsViewerTopComponent.java:108)

我不知道SwingWorker会如何提供帮助。 我在一个单独的线程中执行长时间运行的数据库任务,但是这会在Observable类中调用一个方法(数据库持久化)来通知观察者。

@Override
        public void update(Observable o, final Object arg) {
            final Meaning meng = (Meaning) arg;
            final int row;
            final boolean insert;
            synchronized (mengs) {
                if (mengs.contains(meng)) {
                    row = meng.getObjId();
                    mengs.set(row, meng);
                    insert = false;
                } else {
                    row = mengs.size();
                    mengs.add(row, meng); //last
                    insert = true;
                }
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {

                    @Override
                    public void run() {
                        if (insert) {
                            fireTableRowsInserted(row, row);
                        } else {
                            fireTableRowsUpdated(row, row);
                        }
                    }
                });
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            } catch (InvocationTargetException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

尽管在事件调度线程上触发插入/更新TableModelEvent ,但实际上在执行数据库更新通知的任何线程上都会更新TableModel 这很危险,因为它意味着:

  • 事件调度线程可能会看到TableModel处于不一致状态。
  • 事件调度线程可能正在尝试呈现TableModel因为通知线程正在改变它。

解决方案应该(理论上)只是将您对SwingUtilities.invokeAndWait的调用移到开始的代码块之外: synchronized(mengs) 此外,一旦完成此操作,您实际上可以完全删除synchronized关键字,因为对模型的所有访问都将在EDT上完成。

Observable我会避免使用Observer / Observable类(有关更多信息,请参阅我对此问题的回答 ); 更好地定义特定于域的侦听器接口和事件类(子类java.util.EventObject )。

你的索引是否正确?

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 

上面的语句说你只在数组列表中有一个条目。 我不知道你的代码是“添加”还是“更新”。 但请记住,ResultSet索引是基于1而不是基于0,所以可能需要从所有行值中减去1?

一种选择是使用org.jdesktop.application.Task 您需要将TableModel传递给Task,然后再进行简单的TableModel.insert调用。

注意:任务只是围绕Thread的一个很好的包装器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM