Как определить, когда основной поток заморозить графический интерфейс в Java? - PullRequest
2 голосов
/ 17 декабря 2011

Я хочу определить, когда некоторые операции потребления времени в главном потоке вызывают зависание графического интерфейса. Моя цель - установить и сбросить курсор ожидания автоматически.

спасибо

Ответы [ 4 ]

5 голосов
/ 17 декабря 2011

Я думаю, что вы ставите корзину перед лошадью: ваш главный поток не должен выполнять никаких трудоемких операций, во-первых - они всегда должны выводиться в отдельных потоках, чтобы ваш GUI мог оставаться отзывчивым (инапример, показать статус операций или предоставить возможность их отмены).

2 голосов
/ 19 декабря 2011
2 голосов
/ 17 декабря 2011

У вас может быть поток, который опрашивает трассировку стека потока GUI, чтобы определить, свободен он или занят. Если вы заняты слишком часто, вы можете записать, что он делает (трассировка стека) в журнал. Первоначально было бы интересно записать каждую трассировку неиспользуемого стека и определить, какие из них не стоит регистрировать.

0 голосов
/ 04 мая 2019

Этот код обнаружения блокировки EDT сделает эту работу, добавив сторожей.

EventQueueWithWD.java:

<code>import java.awt.*;
import java.awt.event.*;
import java.util.*;

/**
 * Alternative events dispatching queue. The benefit over the
 * default Event Dispatch queue is that you can add as many
 * watchdog timers as you need and they will trigger arbitrary
 * actions when processing of single event will take longer than
 * one timer period.
 * <p/>
 * Timers can be of two types:
 * <ul>
 * <li><b>Repetitive</b> - action can be triggered multiple times
 * for the same "lengthy" event dispatching.
 * </li>
 * <li><b>Non-repetitive</b> - action can be triggered only once
 * per event dispatching.</li>
 * </ul>
 * <p/>
 * The queue records time of the event dispatching start.  This
 * time is used by the timers to check if dispatching takes
 * longer than their periods. If so the timers trigger associated
 * actions.
 * <p/>
 * In order to use this queue application should call
 * <code>install()</code> method. This method will create,
 * initialize and register the alternative queue as appropriate.
 * It also will return the instance of the queue for further
 * interactions. Here's an example of how it can be done:
 * <p/>
 * <pre>
 * <p/>
 *  EventQueueWithWD queue = EventQueueWithWD.install();
 *  Action edtOverloadReport = ...;
 * <p/>
 *  // install single-shot wg to report EDT overload after
 *  // 10-seconds timeout
 *  queue.addWatchdog(10000, edtOverloadReport, false);
 * <p/>
 * 
* / открытый класс EventQueueWithWD extends EventQueue {// Mainтаймер приватный финал java.util.Timer timer = new java.util.Timer (true);// Группа информационных полей для описания приватного события final Object EventChangeLock = new Object ();private volatile long eventDispatchingStart = -1;частное энергозависимое событие AWTEvent = null;/ ** * Скрытый служебный конструктор.* / private EventQueueWithWD () {} / ** * Установить альтернативную очередь.* * @ Возврат установленного экземпляра очереди.* / public static EventQueueWithWD install () {EventQueue eventQueue = Toolkit.getDefaultToolkit (). getSystemEventQueue ();EventQueueWithWD newEventQueue = new EventQueueWithWD ();eventQueue.push (newEventQueue);return newEventQueue;} / ** * Запишите событие и продолжите обычную диспетчеризацию.* * @param anEvent событие для отправки.* / protected void dispatchEvent (AWTEvent anEvent) {setEventDispatchingStart (anEvent, System.currentTimeMillis ());super.dispatchEvent (anEvent);setEventDispatchingStart (null, -1);} / ** * Регистрация события и время начала диспетчеризации.* * @param anEvent event.* @param timestamp время начала отправки.* / private void setEventDispatchingStart (AWTEvent anEvent, длинная отметка времени) {synchronized (eventChangeLock) {event = anEvent;eventDispatchingStart = timestamp;}} / ** * Добавить сторожевой таймер.Таймер сработает listener *, если событие отправки очереди длиннее указанного * maxProcessingTime.Если таймер * repetitive, то он вызовет дополнительные * события, если обработка 2x, 3x и более дольше, чем * maxProcessingTime.* * @param maxProcessingTime максимальное время обработки.* @param listener listener для событий.Слушатель * получит AWTEvent * в качестве источника события.* @param повторяющееся ИСТИНА для запуска последующих событий * для 2x, 3x и последующих периодов.* / public void addWatchdog (long maxProcessingTime, прослушиватель ActionListener, логическое повторение) {Watchdog checker = new Watchdog (maxProcessingTime, listener, повторение);timer.schedule (checker, maxProcessingTime, maxProcessingTime);} / ** * Проверяет, является ли обработка события более длительной, чем * указанный maxProcessingTime.Если так, то * слушатель получает уведомление.* / закрытый класс Watchdog extends TimerTask {// Настройки приватного финала long maxProcessingTime;приватный финальный слушатель ActionListener;закрытый финальный логический повтор;// Событие сообщается как "продолжительное" в последний раз.Используется для // предотвращения повторяющегося поведения в неповторяющихся таймерах.private AWTEvent lastReportedEvent = null;/ ** * Создает таймер.* * @param maxProcessingTime максимальное время обработки события * до уведомления слушателя.* слушатель @param слушатель, чтобы уведомить.* @param повторяющееся ИСТИНА для разрешения последующих * уведомлений об одном и том же событии * / private Watchdog (длинный maxProcessingTime, слушатель ActionListener, логический повтор)) {if (listener == null) выдает новое исключение IllegalArgumentException («Listener не может быть нулевым.»);if (maxProcessingTime <0) генерирует новое IllegalArgumentException («Максимальный период блокировки должен быть больше нуля»);this.maxProcessingTime = maxProcessingTime;this.listener = слушатель;this.repetitive = повторяющийся;} public void run () {долгое время;AWTEvent currentEvent;// Получить текущие реквизиты событиясинхронизированный (eventChangeLock) { time = eventDispatchingStart; currentEvent = событие; } long currentTime = System.currentTimeMillis (); // Проверяем, обрабатывается ли событие дольше допустимого if (time! = -1 && (currentTime - time> maxProcessingTime) && (повторяющиеся || currentEvent! = lastReportedEvent)) { listener.actionPerformed ( новый ActionEvent (currentEvent, -1, null)); lastReportedEvent = currentEvent; } } } }

SampleEQUsage.java

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.Date;

/**
 * Sample usage of <code>EventQueueWithWD</code> class.
 */
public class SampleEQUsage extends JFrame
{
    public SampleEQUsage()
    {
        super("Sample EQ Usage");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        getContentPane().add(new JButton(new AbstractAction("Go")
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println();
                System.out.println(new Date());
                try
                {
                    // Sleep for 10 seconds
                    Thread.sleep(10000);
                } catch (InterruptedException e1)
                {
                }
            }
        }));

        setSize(100, 100);
    }

    public static void main(String[] args)
    {
        initQueue();

        SampleEQUsage sequ = new SampleEQUsage();
        sequ.setVisible(true);
    }

    // Install and init the alternative queue
    private static void initQueue()
    {
        EventQueueWithWD queue = EventQueueWithWD.install();

        // Install 3-seconds single-shot watchdog timer
        queue.addWatchdog(3000, new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println(new Date() + " 3 seconds - single-shot");
            }
        }, false);

        // Install 3-seconds multi-shot watchdog timer
        queue.addWatchdog(3000, new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println(new Date() + " 3 seconds - multi-shot");
            }
        }, true);

        // Install 11-seconds multi-shot watchdog timer
        queue.addWatchdog(11000, new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println(new Date() + " 11 seconds - multi-shot");
            }
        }, true);
    }
}
...