JAVA—JTable&;的奇怪问题(可能是线程问题);模型

JAVA—JTable&;的奇怪问题(可能是线程问题);模型,java,swing,multithreading,jtable,exception,Java,Swing,Multithreading,Jtable,Exception,我使用2个表(JTable)及其DefaultTableModels。 第一个表已填充。 为第一个表的每一行填充第二个表(使用SQL查询)。 我的目的是在Excel文件中导出第一个表的每一行以及第二个表的相应行 我用for(第一个表格的每一行)来做这件事,我在Excel文件中写下第一个表格的一行,然后我填充第二个表格(第一个表格的这一行),我从表格中得到每一行(实际上是从它的模型中),并将它放在第一个表格当前行下的Excel文件中。 这意味着,如果第一个表中有n行,我将清除并再次填充第二个表n次

我使用2个表(JTable)及其DefaultTableModels。 第一个表已填充。 为第一个表的每一行填充第二个表(使用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.repainmanager.paint(repainmanager.java:1220) 位于javax.swing.repainmanager.paintDirtyRegions(repainmanager.java:803)

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

你当然会问我:

  • 如果你的程序运行得很好,为什么你会关心异常呢? 我希望避免将来出现任何问题,并且希望更好地理解Java和Java GUI以及线程

  • 为什么您依赖GUI组件(及其模型)来获取信息,为什么不重新创建使用SQL查询填充表的结果集并从结果集获取信息? 这将是最好和正确的方式。事实上,我已经准备好了表代码,而且我更容易从表中获取信息。但正确的方法是直接从数据库获取所有信息。不管怎样,我所做的事情引出了我的问题,回答它将帮助我了解更多关于java的事情。所以我把它贴了出来


发生异常是因为其中一个表模型为getValueAt(int行,int列)调用返回null。原因可能是swing或数据模型中存在内部问题,因为您正在使用辅助线程访问数据模型。SwingAPI特别声明,您不能以所描述的方式使用辅助线程

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


Swing API不是线程安全的,除了几个方法调用:重新绘制、重新验证和失效。除非对特定类另有说明,否则所有其他调用都必须在事件调度线程上进行

可以通过SwingUtilities.invokeLater()或SwingUtilities.invokeAndWait()从派生的后台/工作线程传输此类调用处理

对于JTable和中附加到它的实例的任何TableModel,也有一些具体的讨论。两者都不是线程安全的,因此任何从它们访问数据的调用都必须在事件分派线程上执行


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

谢谢。我应该读一些关于Swing和Threads的东西。