4

I'm making a simple game in Java using swing and am having problems with my GUI freezing up sporadically (due to threading issues most probably) after a button press that is supposed to trigger a switch in JPanels.

I posted a related thread here, which has more details about the actual code I'm currently using (although I did update the countdown and get that working fine). From answers to that thread, it seems like usingSwingUtilities.invokeLater() or invokeAndWait() might be what I need to solve the problem, but I'm not sure where in my code it is necessary or exactly how to implement it.

I don't know that much about threading and could use any help (preferably somewhat detailed and with some sample code) that I can get. Let me know if any further details would be useful.

asked Feb 29, 2012 at 22:30
5
  • 2
    Are you calling Thread.sleep(...) on the event thread (the EDT)? Commented Feb 29, 2012 at 22:34
  • no, not anymore. I rewrote the part of the code that was previously doing that. Commented Feb 29, 2012 at 22:53
  • @scae Can you share your code which updates the response to component? Commented Feb 29, 2012 at 23:01
  • @CengizCan Did you look over the code I posted on the page that I linked to in my question? That has basically all the code that should be relevant to this issue. Commented Feb 29, 2012 at 23:07
  • 1
    If your GUI freezes you can get a thread dump with jstack (find process ID with jps), or from the sonsole ctrl-break (Windows) or ctrl-3/`ctrl-` (IIRC, Linux). Commented Feb 29, 2012 at 23:21

4 Answers 4

4

See: Tutorial: Concurrency in Swing

Generally speaking, the Event Dispatch Thread is a single thread, chugging through the event queue, processing one at a time.

SwingUtilities.invokeLater(..) 

puts a Runnable on this queue. So it will be processed by the EDT when the EDT finishes everything on the queue before it (This is why sleeping on the queue blocks other events like repainting). It's relatively unusual to call invokeLater(..) from the EDT itself, though there are situations where it is useful (usually as a hack). I don't think I have had a legitimate use for SwingUtilities.invokeAndWait(..) in the last 6 years. Maybe once.

javax.swing.Timer can be configured to fire once or periodically. When it fires, it puts an event on the EDT queue. If you have computationally-intensive processing that need to be done, consider using javax.swing.SwingWorker to do the computation on another thread, and give you back the result in a thread-safe manner (this is also comparatively rare).

answered Feb 29, 2012 at 22:51

3 Comments

Thanks for the explanation. Could you help me figure out what is wrong in my code in specific, though, and how to fix it (I'm not quite sure where the EDT starts/ends and where I'd need to use an invokeLater() to add something to the EDT queue)?
Try creating a SSCCE (sscce.org) that demonstrates your problem. Distilling the problem may help you solve it on your own, otherwise, post it here and people will be able to give you more specific advice.
thanks! I did that and it turns out it was something that I'd thought was entirely unrelated (non GUI stuff) that was causing the freeze.
1

A good point to look is the docs. In your case, this explains how SwingUtilities.invokeLater() works and where to use it:

Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This method should be used when an application thread needs to update the GUI.

So, in your actions that modifies the GUI you must use the invokeLater method to assure that the GUI wont freeze.

Another good resource is the Java tutorials. They cover concurrency in Swing.

answered Feb 29, 2012 at 22:52

1 Comment

ok, I understand that I will need to use invokeLater() to stop the freezing by adding some bit of code to the EDT queue, but where in my code do I need to do this? I experimented with adding it to a few different places that I thought would make sense, but none of my ideas fixed it so I'm obviously missing something (for code samples/program outline look at my other post).
0

I have create a WorkerThread class which take care of Threads and GUI current/main thread . i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look. /** * Action Event * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent ae) { log.info("actionPerformed begin..." + ae.getActionCommand());

 try {
 if (ae.getActionCommand().equals(btnStart.getText())) {
 final int portNumber = 9990;
 try {
 WorkerThread workerThread = new WorkerThread(){
 public Object construct(){
 log.info("Initializing the XXXServer ...");
 // initializing the Socket Server
 try {
 XXXServer xxxServer = new XXXServer(portNumber);
 xxxServer.start();
 btnStart.setEnabled(false); 
 } catch (IOException e) {
 // TODO Auto-generated catch block
 log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
 e.printStackTrace();
 }
 return null;
 }
 };workerThread.start();
 } catch (Exception e) {
 log.info("actionPerformed() Start button ERROR..." + e.getMessage());
 e.printStackTrace();
 }
 } else if (ae.getActionCommand().equals(btnStop.getText())) {
 log.info("Exit..." + btnStop.getText());
 closeWindow();
 }
 } catch (Exception e) {
 log
 .info("Error in ServerGUI actionPerformed==="
 + e.getMessage());
 }
}
answered Dec 23, 2014 at 12:40

Comments

0

In order to invoke an action in the existing WorkerThread, one would intuitively send a user defined event using SwingUtilities.invokeLater() to a JFrame's actionPerformed() method as

class TestFrame extends JFrame implements ActionListener
{
...
 private class Performer implements Runnable
 {
 ActionEvent event;
 Performer(ActionEvent event)
 {
 this.event = event;
 }
 @Override
 public void run()
 {
 actionPerformed(event);
 }
 }
 synchronized protected void invokeLater(ActionEvent event)
 {
 SwingUtilities.invokeLater(new Performer(event));
 }
 public void actionPerformed(ActionEvent event)
 {
 ...
 }
}

Now, TestFrame.invokeLater() called in any Thread will be processed in TestFrame.actionPerformed() in existing WorkerThread .

answered Nov 22, 2020 at 13:39

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.