当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Will the update method of an Observer be executed on the event dispatch thread

问题描述:

If I have a JFrame which implements the Observer interface, will the update() method be executed on the event dispatch thread?

public class MyFrame extends JFrame implements Observer{

@Override

public void update(Observable o, Object arg) {

//do gui stuff

}

}

.

public class MyTask extends Observable implements Runnable{

@Override

public void run() {

setChanged();

notifyObservers("Update!");

}

}

网友答案:

As I just found out by myself:

No, it will be executed on the Thread that called the notifyObservers() method.

As you can see from the source code, the notifyObservers() method, it just calles the update() method of the observer, without passing the task to another thread.

public void notifyObservers(Object arg) {
    /*
    * a temporary array buffer, used as a snapshot of the state of
    * current Observers.
    */
    Object[] arrLocal;

    synchronized (this) {
        if (!changed)
            return;
        arrLocal = obs.toArray();
        clearChanged();
    }

    for (int i = arrLocal.length-1; i>=0; i--)
        ((Observer)arrLocal[i]).update(this, arg);
    }
}
网友答案:

If you want to do what I think you're trying to do, you can use a SwingWorker. It has a publish method and process method. The publish method will send messages to the process method. The process method, unlike the rest of the SwingWorker, runs on the EDT.

import java.awt.EventQueue;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JFrame;

import javax.swing.SwingWorker;


public class MyFrame extends JFrame {

    private static JTextField txtFld;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
                new UpdateSwingWorker().execute();
            }
        });    
    }

    private static void createAndShowGUI() {
        MyFrame frame = new MyFrame();

        JPanel panel = new JPanel(new BorderLayout());
        txtFld = new JTextField();
        panel.add(txtFld, BorderLayout.CENTER);

        frame.setSize(new Dimension(300,200));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300,200));
        frame.setLayout(new BorderLayout());
        frame.add(panel, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);     
    }

    private static class UpdateSwingWorker extends SwingWorker<Void, String> {

        @Override
        protected Void doInBackground() throws Exception {
            // Do your work...
            System.out.println("Thread in doInBackground: " + Thread.currentThread());
            publish("Updated");
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            System.out.println("Thread in process: " + Thread.currentThread());
            txtFld.setText(chunks != null ? chunks.get(0) : "");
        }

    }

}

Or, if you really want to use the Observer pattern, you could wrap the notifyObservers call in EventQueue's invokeLater call. This method causes Runnable to have its run method happen in the EDT.

Frame:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class MyFrame2 extends JFrame implements Observer {
    private static JTextField txtFld;

    private static MyTask task = new MyTask();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
                new Thread(task).start();
            }
        });    
    }

    private static void createAndShowGUI() {
        MyFrame2 frame = new MyFrame2();
        task.addObserver(frame);

        JPanel panel = new JPanel(new BorderLayout());
        txtFld = new JTextField();
        panel.add(txtFld, BorderLayout.CENTER);

        frame.setSize(new Dimension(300,200));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300,200));
        frame.setLayout(new BorderLayout());
        frame.add(panel, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);     
    }

    @Override
    public void update(Observable o, Object arg) {

        System.out.println("Thread in update: " + Thread.currentThread());
        txtFld.setText((String) arg);
    }

}

Task:

import java.awt.EventQueue;
import java.util.Observable;

public class MyTask extends Observable implements Runnable {

    @Override
    public void run() {
        // Do work
        System.out.println("Thread in run: " + Thread.currentThread());
        setChanged();

        // Notify the observers on the EDT.
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                System.out.println("Thread in invokeLater: " + Thread.currentThread());
                notifyObservers("Update!");
            }
        });
    }

}
分享给朋友:
您可能感兴趣的文章:
随机阅读: