создать новый поток внутри проблемы actionPerformed и Event Dispatch Thread (EDT)

Как заявил Sun, actionPerformed() из ActionListener автоматически выполняется в EDT, поэтому я решил создать новый поток внутри метода actionPerformed(), и проблема в том, что этот поток не выполняется внутри EDT. Кто-нибудь может это объяснить? Спасибо


person MinhHoang    schedule 22.04.2012    source источник


Ответы (2)


Если вы создаете новый поток из EDT, этот поток отличается от EDT. Разве не ясно?
Вы должны обновлять элементы управления через EDT.
Вы можете создавать свои собственные фоновые потоки для тяжелых задач, но обновление элементов управления должно производиться только через EDT. Существуют конструкции, которые вы можете использовать для облегчения кода, например. передать Runnable для вызова EDT через SwingUtilities вызывает Runnable. Вам следует изучить параллелизм в Swing

person Cratylus    schedule 22.04.2012
comment
invokeAndWait невозможно запустить из actionPerformed(), потому что этот поток может завершиться в EDT, а затем вернуть несколько exception, нехорошее предложение - person mKorbel; 22.04.2012
comment
Привет, я знаю, что обновления управления должны быть внутри EDT. Я просто подумал, что вновь созданный поток будет совместно использовать EDT, поскольку он уже находится в среде EDT ›.‹ - person MinhHoang; 22.04.2012
comment
@mKorbel: Хорошая мысль. Но я подозреваю, что он хотел создать фоновый поток для какой-то задачи, а затем обновить графический интерфейс, что является обычной ошибкой новичков в Swing. Я обновлю ответ, чтобы прояснить это. - person Cratylus; 22.04.2012
comment
@FinalIllusion: EDT — это поток. А именно Event Dispatch Thread. Если внутри EDT вы создаете новый поток, то этот поток является другим потоком выполнения. - person Cratylus; 22.04.2012
comment
Получается, что я не могу обернуть thread.start() внутри статического метода EvenQueue.invokeLater() внутри actionPerformed(). Что я могу сделать, чтобы исправить это? - person MinhHoang; 22.04.2012
comment
@FinalIllusion: Почему бы вам не рассказать нам, чего вы пытаетесь достичь с помощью этого кода, чтобы мы сказали вам, как это сделать правильно? - person Cratylus; 22.04.2012
comment
Привет, спасибо, ребята! Я понял проблему, и ключ - это вновь созданный поток, который выполняется в другом потоке, несмотря на то, что он создается внутри EDT. Я решил это, теперь он работает как шарм ^^ - person MinhHoang; 22.04.2012

1) AWT или Swing GUI вызывается и создается EDT, это событие выполняется (возможно, есть и другие) методами pack() и setVisible(true)

2) если все события, ожидающие в EDT, выполнены, а EDT пуст, тогда if (EventQueue.isDispatchThread()) { возвращает false, но поток EDT существует до тех пор, пока не существует текущий экземпляр JVM

3) как уже упоминалось, для очереди вызова EDT вы можете использовать invokeLater или invokeAndWait, обратите внимание, invokeAndWait вы можете использовать, только если isDispatchThread возвращает false, в противном случае возвращает исключения

4) вызов Thread.sleep(int) из Swing Listener или его метод может заморозить и заблокировать EDT, что приведет к потере некоторого события из очереди событий,

пример двух кодов для тестирования isDispatchThread() и как активировать EDT из объектов Java

import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class IsThereEDT {

    private ScheduledExecutorService scheduler;
    private AccurateScheduledRunnable periodic;
    private ScheduledFuture<?> periodicMonitor;
    private int taskPeriod = 30;
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    private Date dateRun;
    private JFrame frame1 = new JFrame("Frame 1");

    public IsThereEDT() {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        periodic = new AccurateScheduledRunnable() {

            private final int ALLOWED_TARDINESS = 200;
            private int countRun = 0;
            private int countCalled = 0;
            private int maxCalled = 10;

            @Override
            public void run() {
                countCalled++;
                if (countCalled < maxCalled) {
                    if (countCalled % 3 == 0) {
                        /*if (EventQueue.isDispatchThread()) {
                            SwingUtilities.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    //some stuff
                                }
                            });
                        } else {
                            try {
                                SwingUtilities.invokeAndWait(new Runnable() {

                                    @Override
                                    public void run() {
                                        //some stuff
                                    }
                                });
                            } catch (InterruptedException ex) {
                                Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (InvocationTargetException ex) {
                                Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }*/
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                System.out.println("Push a new event to EDT");
                                frame1.repaint();
                                isThereReallyEDT();
                            }
                        });
                    } else {
                        if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                            countRun++;
                            isThereReallyEDT(); // non on EDT
                        }
                    }
                } else {
                    System.out.println("Terminating this madness");
                    System.exit(0);
                }
            }
        };
        periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
        periodic.setThreadMonitor(periodicMonitor);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                isThereReallyEDT();
                frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame1.getContentPane().add(new JLabel("Hello in frame 1"));
                frame1.pack();
                frame1.setLocation(100, 100);
                frame1.setVisible(true);
            }
        });
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame2 = new JFrame("Frame 2");
                frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame2.getContentPane().add(new JLabel("Hello in frame 2"));
                frame2.pack();
                frame2.setLocation(200, 200);
                frame2.setVisible(true);
                isThereReallyEDT();
            }
        });
    }

    private void isThereReallyEDT() {
        dateRun = new java.util.Date();
        System.out.println("                         Time at : " + sdf.format(dateRun));
        if (EventQueue.isDispatchThread()) {
            System.out.println("EventQueue.isDispatchThread");
        } else {
            System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
        }
        if (SwingUtilities.isEventDispatchThread()) {
            System.out.println("SwingUtilities.isEventDispatchThread");
        } else {
            System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        IsThereEDT isdt = new IsThereEDT();
    }
}

abstract class AccurateScheduledRunnable implements Runnable {

    private ScheduledFuture<?> thisThreadsMonitor;

    public void setThreadMonitor(ScheduledFuture<?> monitor) {
        this.thisThreadsMonitor = monitor;
    }

    protected long getExecutionTime() {
        long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
        return delay;
    }
}

и более простой код

.

.

import java.awt.EventQueue;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class IsThereEDT {

    private ScheduledExecutorService scheduler;
    private AccurateScheduledRunnable periodic;
    private ScheduledFuture<?> periodicMonitor;
    private int taskPeriod = 30;
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    private Date dateRun;
    private JFrame frame1 = new JFrame("Frame 1");

    public IsThereEDT() {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        periodic = new AccurateScheduledRunnable() {

            private final int ALLOWED_TARDINESS = 200;
            private int countRun = 0;
            private int countCalled = 0;
            private int maxCalled = 10;

            @Override
            public void run() {
                countCalled++;
                if (countCalled < maxCalled) {
                    if (countCalled % 3 == 0) {
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                System.out.println("Push a new event to EDT");
                                frame1.repaint();
                                isThereReallyEDT();
                            }
                        });
                    } else {
                        if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                            countRun++;
                            isThereReallyEDT(); // non on EDT
                        }
                    }
                } else {
                    System.out.println("Terminating this madness");
                    System.exit(0);
                }
            }
        };
        periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
        periodic.setThreadMonitor(periodicMonitor);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                isThereReallyEDT();
                frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame1.getContentPane().add(new JLabel("Hello in frame 1"));
                frame1.pack();
                frame1.setLocation(100, 100);
                frame1.setVisible(true);
            }
        });
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame2 = new JFrame("Frame 2");
                frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame2.getContentPane().add(new JLabel("Hello in frame 2"));
                frame2.pack();
                frame2.setLocation(200, 200);
                frame2.setVisible(true);
                isThereReallyEDT();
            }
        });
    }

    private void isThereReallyEDT() {
        dateRun = new java.util.Date();
        System.out.println("                         Time at : " + sdf.format(dateRun));
        if (EventQueue.isDispatchThread()) {
            System.out.println("EventQueue.isDispatchThread");
        } else {
            System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
        }
        if (SwingUtilities.isEventDispatchThread()) {
            System.out.println("SwingUtilities.isEventDispatchThread");
        } else {
            System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        IsThereEDT isdt = new IsThereEDT();
    }
}

abstract class AccurateScheduledRunnable implements Runnable {

    private ScheduledFuture<?> thisThreadsMonitor;

    public void setThreadMonitor(ScheduledFuture<?> monitor) {
        this.thisThreadsMonitor = monitor;
    }

    protected long getExecutionTime() {
        long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
        return delay;
    }
}
person mKorbel    schedule 22.04.2012