0

There is actually more than 1 question.

Given Model View and Controller. (Mine are coupled a lot - View knows its Controller, and Controller knows View.)

Does new threads in Controller can be fired in basic manner - with the new Runnable(){ (...) run(){}} or it is required to do in some "swing way", to make it properly? Maybe with Timer or invokeLater()?

Second thing is - assuming that new thread has started - when it operates directly on view, setting some JTextFields (and so on) - do methods such as setThatTextFieldWithNewValue(msg) need to be synchronized as a result of being called from need thread? If so - is there any better approach that gives less coupling and less spend time thinking about needed synchronization?

dantuch
  • 9,123
  • 6
  • 45
  • 68

4 Answers4

2

Swing is not Thread-Safe

1. The UI thread is the Event Dispatcher Thread, which is responsible for the Gui work.

2. Try working with Non-Ui threads outside the UI thread.

3. Yes offcourse you can fire a thread from within the UI thread, but its advisable to keep it out of the UI thread, else the GUI may seems non-responsive.

(ie. the Non-UI work on the Non-UI thread OUT of the UI thread which is responsible for the UI Work)

4. Well there is a swing way too... use SwingWorker, this handles the synchronization between UI and Non-UI thread.

Edited part:

// PLEASE NOTE ITS NOT GOOD TO ADD COMPONENTS DIRECTLY ON THE FRAME/JFRAME, BUT I AM DOING THIS JUST TO SHOW, WHAT I MEANT.

public class MyClass extends JFrame{

private final JButton b;

 public MyClass(){

  this.setSize(300,300);
  this.setComponent();
  this.setHandler();
}

public void setComponent(){

  b = new JButton("Click");
  this.add(b);

}

public void setHandler(){

  b.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent arg0) {

            // Do whatever you want...      

    }
});

}

public static void main (String[] args) { 
      EventQueue.invokeLater(new Runnable(){    // UI THREAD
        public void run(){

         MyClass s = new MyClass();   
         s.setVisible(true);
        }

      });
   }
}

Main method is short lived in Swing, The main method() schedules the Construction of GUI to the Event Dispatcher Thread (EDT), and then quits. So its EDT responsibility to handle the GUI. So its always advisable to keep the Non-UI work on the Non-UI thread away from EDT.

Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
  • _Try working with Non-Ui threads outside the UI thread._ ... _you can fire a thread the normal way, but its advisable to keep it out of the UI thread_ What does this mean? – Guillaume Polet Jul 12 '12 at 08:06
  • I am really sorry, by mistake i misphrased the sentence... And thanks @polet that you pointed that out..I have rephrased the particular sentence..thanks once again – Kumar Vivek Mitra Jul 12 '12 at 09:07
  • would you please stop shouting all the time - we are not blind ;-) – kleopatra Jul 12 '12 at 09:56
  • btw: the "please note" is plainly wrong, mixing (? intentionally) awt and swing is unusual, extending JFrame bad practice ... – kleopatra Jul 12 '12 at 10:01
  • I used Frame over there to symbolize Frame and JFrame, just like we symbolise Man for Man and Woman in some context. So please dont mind it..and i am sorry for the inconvenience you had reading the above exmaple. – Kumar Vivek Mitra Jul 12 '12 at 11:10
  • @KumarVivekMitra you are using a Button (AWT) and a JFrame (Swing). I still don't see how you fixed your sentences. Threads are separate flows of instructions execution. Saying a Thread should be out of another Thread does not make sense. Btw, could you please removal all the bold text, it looks like you are shouting; we are neither blind nor deaf. – Guillaume Polet Jul 12 '12 at 13:50
  • I have edited the button part.. due to power failure, my internet connection for served, so sorry for the late update. And yes I did NOT said that `Thread should be out of another Thread`, if you read the 2nd point before the 3rd you will get the idea that i mean `the Non-UI work on the Non-UI thread OUT of the UI thread which is responsible for the UI Work` – Kumar Vivek Mitra Jul 12 '12 at 16:56
2
  1. there are a few ways how is possible to create, manage and notify MVC, for better help sooner post an SSCCE

  2. Runnable#Thread is very confortable, stable and clear way, but I'd suggest to wrap all output to the Swing GUI into invokeLater, including thread safe methods as setText, append e.g. are ..

  3. as Kumar Vivek Mitra (+1) metioned there is SwingWorker, but required deepest knowledge about Java essential classes, some trouble are there with exceptions recycle how to get exception from SwingWorker

  4. about MVC maybe will help you my similair question

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
1

Anything in swing has to run on the EventQueue. If you have a method called from swing it will already be running there (as in an Action listener). If you don't know if you're on the event queue, EventQueue.isDispatchThread() will tell you. When you know you're not, reference a swing class or method using EventQueue.invokeLater() or invokeAndWait if you need to see results. (This must be done from the main method.)

Be very careful about this; you have to check your code. If not, my experience is that the swing UI will be just a little bit flakey, with the occasional unreproducable oddity. There's no easy way around eyeballing each line of code.

Actually, there is. Do everything on the EventQueue, then you won't have to worry. You're probably not doing a whole lot of work outside swing anyway. If you are, it's probably worth the loss of speed to avoid multithreading problems. If your non-swing work is extensive but simple, use the SwingWorker class. It gives you an extra thread under highly controlled conditions and should save you a lot of grief.

Your classes (View and Controller) are independent of threads, and should work just fine all running in one thread. Don't confuse classes and threads. (I'll admit, I'd be tempted to have the Controller firing off threads in all directions, but you have to be prepared to be very careful and know everything there is to know about multithreading.)

If you do multithread, the EventQueue can be a bit handy because you don't have to protect fields referenced only there--it's an island of single threading in a dangerous sea. On the other hand, don't do any synchronization there; you'll block your UI. You can launch threads from there and you may have to just to avoid blocking. (Once you start multithreading, it's hard to stop.)

RalphChapin
  • 3,108
  • 16
  • 18
0

The easiest way would be:

        SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {

            // Run your code here.

        }
    });

For more complex tasks (send process chunks to ui thread, respond to jobFinished):

    new SwingWorker<String, String>() {


        @Override
        protected void done() {

        }

        @Override
        protected void process(List<String> arg0) {


        }

        @Override
        protected String doInBackground() throws Exception {


        }


    }.execute();
Jonas Eicher
  • 1,413
  • 12
  • 18