【问题标题】:JAVA - Strange problem (probably thread problem) with JTable & ModelJAVA - JTable & Model 的奇怪问题(可能是线程问题)
【发布时间】:2011-03-04 10:06:38
【问题描述】:

我正在使用 2 个表 (JTable) 及其 DefaultTableModel。 第一个表已填充。 为第一个表的每一行填充第二个表(使用 SQL 查询)。 我的目的是将第一个表的每一行与 Excel 文件中第二个表的相应行导出。

我正在使用 for(对于第一个表的每一行),其中我在 Excel 文件中写入第一个表的一行,然后填充第二个表(对于第一个表的这一行),我从表中获取每一行(实际上是从它的模型中)并将其放入 Excel 文件中的第一个表的当前行下。 这意味着如果我在第一个表中有 n 行,我将清除并再次填充第二个表 n 次。

所有这些代码都在一个单独的线程中调用。

问题是: 一切都很好,除了我遇到了一些例外。 奇怪的是,我的结果没有任何错误。 Excel 文件是完美的。

一些例外的行是:

线程“AWT-EventQueue-0”中的异常 java.lang.ArrayIndexOutOfBoundsException: 0 >= 0 在 java.util.Vector.elementAt(Vector.java:427) 在 javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:632) 在 javax.swing.JComponent.paint(JComponent.java:1017) 在 javax.swing.RepaintManager.paint(RepaintManager.java:1220) 在 javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:803)

我假设问题在于第二个表需要更多时间来填充,然后才能尝试从中获取任何数据。这就是为什么我在异常中看到 RepaintManager 和 paintDirtyRegions 的原因。 我做的另一件事是我在调试模式下运行我的程序,并在第二个表的每个填充后放置一个断点。然后我按 F5 继续为第二张桌子的每个人口,没有出现异常。该计划无一例外地结束了。 这是另一个重要的事实,它告诉我,也许在这种情况下,我给了表格足够的时间来填充表格。

你当然会问我:

  • 如果您的程序运行良好,为什么还要关心异常? 我希望避免将来出现任何问题,并且希望更好地了解 Java 和 Java GUI 和线程。

  • 为什么要依赖 GUI 组件(及其模型)来获取信息,为什么不使用 SQL 查询重新创建填充表的结果集并从结果集中获取信息? 那将是最好和正确的方法。事实是我已经准备好表格代码,而且我更容易从它们那里获取信息。但正确的方法是直接从数据库中获取所有内容。无论如何,我的所作所为提出了我的问题,回答它会帮助我了解更多关于 java 的东西。所以我贴出来了。

【问题讨论】:

    标签: java swing multithreading jtable exception


    【解决方案1】:

    发生异常是因为表模型之一为 getValueAt(int row,int column) 调用返回 null。其原因可能是 Swing 或数据模型的内部问题,因为您使用辅助线程来访问数据模型。 swing api特别声明您不能按照您描述的方式使用辅助线程。

    以下文章提供了有关 swing 中单线程规则的更多详细信息。

    http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html

    【讨论】:

      【解决方案2】:

      Swing API 不是线程安全的,除了一些方法调用:repaintrevalidateinvalidate。除非对特定类另有说明,否则所有其他调用必须在事件调度线程上进行。

      可以通过 SwingUtilities.invokeLater()SwingUtilities.invokeAndWait() 将此类调用处理从衍生的后台/工作线程转移。

      javax.swing package summary javadocs 中还有一些关于 JTable 和任何附加到它的实例的 TableModel 的具体讨论。两者都不是线程安全的,因此从它们访问数据的任何调用都必须在事件调度线程上执行。

      这是您遇到异常的最可能原因,您在调试器中运行时遇到的不同行为是竞争条件的典型标志。也没有可靠的方法可以通过引入自己的锁等来解决这个问题。从长远来看,这种做法总是会导致麻烦(例如 Swing 库深处的 Event Dispatch Queue 锁的死锁),因为 Swing 真的,真的是并非设计为线程安全的。

      【讨论】:

      • 谢谢。我应该读一些关于 Swing 和 Threads 的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多