Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

JButtons should start Threads whit synchronized handling of a JTable model

 
Matt Kurz
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a simple Swing Gui with 1 JTable, a Searchbutton and a Deletebutton. So I can search content in a MySql DB, show the result in a JTable, mark some rows, and delete the marked rows. So far so good. Now I want that each Klick should start a Thread. Here are the relevant source code snippets:





If I click fast on the button, I get:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 9 >= 0

What is wrong, and how can I do it right?
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The TableModel is not Thread Safe, so you have to be careful with using it in multiple threads. So there are a few things to consider:
1) Preventing multiple threads from modifying the TableModel at one time.
-- The simple solution to this is to disable any of the user interface when the first request is made. For example, the first thing that happens in the actionPerformed method is to disable the button which caused the action. This prevents the user from pressing the button again. Of course at the end of the process you will have to re-enable the button. You should also disable all other buttons which modify the TableModel.

2) Preventing incomplete reads during updates.
-- Since the TableModel is not Thread Safe, your GUI could try to read the model for display purposes while rows are getting written to it. This could lead to displaying garbage data. I would suggest you use a SwingWorker to fix this. You need to push all the calls which update the TableModel into the EventDispatchThread, while keeping all the long DB work outside of it. With SwingWorker, you would put the DB Processing in the doInBackround(). You would put the model update (model.addRow(...)) into the process() method. In the doInBackground() method, when you want to update the GUI with a new row, you call publish() with the data to put into the new row. Finally, in the done() method is where you would do all the GUI clean up (like re-enabling the buttons).
 
Matt Kurz
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Steve Luke wrote:The TableModel is not Thread Safe, so you have to be careful with using it in multiple threads. So there are a few things to consider:
1) Preventing multiple threads from modifying the TableModel at one time.
-- The simple solution to this is to disable any of the user interface when the first request is made. For example, the first thing that happens in the actionPerformed method is to disable the button which caused the action. This prevents the user from pressing the button again. Of course at the end of the process you will have to re-enable the button. You should also disable all other buttons which modify the TableModel.

If I do not work with threads, everything freezes, until the clicked button has finished it's work. So why should I disable all other buttons?


2) Preventing incomplete reads during updates.
-- Since the TableModel is not Thread Safe, your GUI could try to read the model for display purposes while rows are getting written to it. This could lead to displaying garbage data. I would suggest you use a SwingWorker to fix this. You need to push all the calls which update the TableModel into the EventDispatchThread, while keeping all the long DB work outside of it. With SwingWorker, you would put the DB Processing in the doInBackround(). You would put the model update (model.addRow(...)) into the process() method. In the doInBackground() method, when you want to update the GUI with a new row, you call publish() with the data to put into the new row. Finally, in the done() method is where you would do all the GUI clean up (like re-enabling the buttons).

Hmm. Sounds much more difficult than expected. I will read about these stuff. Hope to find good examples. Nevertheless: There is no easy way, like a flag for the first thread, that not other thread should be started, until the first thread sets the flag back?
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matt Kurz wrote:
If I do not work with threads, everything freezes, until the clicked button has finished it's work. So why should I disable all other buttons?


If you don't use threads buoy don't have to worry about two threads modifying the model at once. If you do use threads you have to prevent that from happening. The best way is to disable the buttons because it both makes it safe and notifies the user. You don't have to disable all buttons, just those that modify the table.


Hmm. Sounds much more difficult than expected. I will read about these stuff. Hope to find good examples. Nevertheless: There is no easy way, like a flag for the first thread, that not other thread should be started, until the first thread sets the flag back?


You should read more on it. You could set a simple flag but there are issues about it's visibility, and it won't prevent problems associated with trying to display which may be partially formed as the table gets built. You will end up with glitchy displays.
 
Javin Paul
Ranch Hand
Posts: 295
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

if you want to use a variable or flag to see if some other thread already working , you need to make it volatile so that no thread caches its value and always gets value from main memory.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic