Search code examples
javaswingconcurrencyjtablejtableheader

Building a concurrent TableColumnAdjuster for JTable


I copied a TableColumnAdjuster class which seems to be pretty popular. http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/

However, the JTables I am developing are dynamic and can have a large amount of data flow in and out of them (as much as 30,000 records). Obviously, when the TableColumnAdjuster has to iterate through every cell it can take awhile and make the Swing interface unresponsive. I tried putting the adjustColumns() method on its own thread, but the columns began to resize wildly and randomly. Obviously not threadsafe. So I started to reverse engineer the class, turning variables into volatiles, replacing the hashmap with a concurrent hash map, and separating the calculation from the Swing invokeLater() thread.

However, nothing is working and the columns still resize wildly. I'm beginning to wonder if the JTable is not threadsafe altogether. Is JTable even threadsafe for tasks like this? Is there a somewhat simple, strategic insertion of code to make the adjustColumns() run on a separate thread safely? And interact with the Swing thread when it has updates for the view?


Solution

  • Doesn't answer your question about making the code Thread safe since it assumes the code is executing on the EDT. I'm not surehow you would restructure the code to use SwingWorkers as the problem is you could still be updating the TableModel while the TableColumnAdjuster is doing its processing.

    large amount of data flow in and out of them (as much as 30,000 records).

    With 30K records does the width of each column change drastically from one record to the next AFTER you have determined the initial widths for the initial data?

    I mean chances are if you change a cell containing the maximum width, the next greatest width will only be 1 lower given 30K records. So do you really need to change the width lower by 1? The user is not going to worry if the column width doesn't change because as far as they are concerned the largest width could anyone of the other 30K rows.

    So, maybe you can get away with using the onlyAdjustLarger property. This should only need to look at the current row that was changed to see if the width needs to be increased. Since the user is currently viewing this row it would make sense to increase the width right away.

    You would need to modify the tableChanged(...) code for this. Instead of invoking adjustColumns() all the time you would only invoke it when the onlyAdjustLarger property is false. In all other cases you would only need to check the columns and rows that were updated.