我想检测主线程中的某些时间消耗操作导致gui冻结。 我的目标是自动设置和取消设置等待光标。
感谢
答案 0 :(得分:5)
我认为你将推车放在马前:你的主线程首先不应该进行任何耗时的操作 - 它们应该总是在不同的线程中外部化,这样你的GUI就能保持响应(和例如,显示操作状态,或提供中止操作的可能性。)
答案 1 :(得分:2)
您可以拥有一个线程来轮询GUI线程的堆栈跟踪,以确定它是空闲还是忙碌。如果太忙,您可以将其正在执行的操作(堆栈跟踪)记录到日志中。最初,记录每个非空闲堆栈跟踪并确定哪些不值得记录可能会很有趣。
答案 2 :(得分:2)
我认为这可能有所帮助:http://www.javaspecialists.eu/archive/Issue075.html和http://www.javaworld.com/javaworld/javatips/jw-javatip87.html。
答案 3 :(得分:0)
This EDT锁定检测代码将通过添加看门狗来完成这项工作。
EventQueueWithWD.java
:
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/>
* </pre>
*/
public class EventQueueWithWD extends EventQueue {
// Main timer
private final java.util.Timer timer = new java.util.Timer(true);
// Group of informational fields for describing the event
private final Object eventChangeLock = new Object();
private volatile long eventDispatchingStart = -1;
private volatile AWTEvent event = null;
/**
* Hidden utility constructor.
*/
private EventQueueWithWD() { }
/**
* Install alternative queue.
*
* @return instance of queue installed.
*/
public static EventQueueWithWD install() {
EventQueue eventQueue =
Toolkit.getDefaultToolkit().getSystemEventQueue();
EventQueueWithWD newEventQueue = new EventQueueWithWD();
eventQueue.push(newEventQueue);
return newEventQueue;
}
/**
* Record the event and continue with usual dispatching.
*
* @param anEvent event to dispatch.
*/
protected void dispatchEvent(AWTEvent anEvent) {
setEventDispatchingStart(anEvent, System.currentTimeMillis());
super.dispatchEvent(anEvent);
setEventDispatchingStart(null, -1);
}
/**
* Register event and dispatching start time.
*
* @param anEvent event.
* @param timestamp dispatching start time.
*/
private void setEventDispatchingStart(AWTEvent anEvent,
long timestamp) {
synchronized (eventChangeLock) {
event = anEvent;
eventDispatchingStart = timestamp;
}
}
/**
* Add watchdog timer. Timer will trigger <code>listener</code>
* if the queue dispatching event longer than specified
* <code>maxProcessingTime</code>. If the timer is
* <code>repetitive</code> then it will trigger additional
* events if the processing 2x, 3x and further longer than
* <code>maxProcessingTime</code>.
*
* @param maxProcessingTime maximum processing time.
* @param listener listener for events. The listener
* will receive <code>AWTEvent</code>
* as source of event.
* @param repetitive TRUE to trigger consequent events
* for 2x, 3x and further periods.
*/
public void addWatchdog(long maxProcessingTime,
ActionListener listener,
boolean repetitive) {
Watchdog checker = new Watchdog(maxProcessingTime, listener,
repetitive);
timer.schedule(checker, maxProcessingTime,
maxProcessingTime);
}
/**
* Checks if the processing of the event is longer than the
* specified <code>maxProcessingTime</code>. If so then
* listener is notified.
*/
private class Watchdog extends TimerTask {
// Settings
private final long maxProcessingTime;
private final ActionListener listener;
private final boolean repetitive;
// Event reported as "lengthy" for the last time. Used to
// prevent repetitive behaviour in non-repeatitive timers.
private AWTEvent lastReportedEvent = null;
/**
* Creates timer.
*
* @param maxProcessingTime maximum event processing time
* before listener is notified.
* @param listener listener to notify.
* @param repetitive TRUE to allow consequent
* notifications for the same event
*/
private Watchdog(long maxProcessingTime,
ActionListener listener,
boolean repetitive) {
if (listener == null)
throw new IllegalArgumentException(
"Listener cannot be null.");
if (maxProcessingTime < 0)
throw new IllegalArgumentException(
"Max locking period should be greater than zero");
this.maxProcessingTime = maxProcessingTime;
this.listener = listener;
this.repetitive = repetitive;
}
public void run() {
long time;
AWTEvent currentEvent;
// Get current event requisites
synchronized (eventChangeLock) {
time = eventDispatchingStart;
currentEvent = event;
}
long currentTime = System.currentTimeMillis();
// Check if event is being processed longer than allowed
if (time != -1 && (currentTime - time > maxProcessingTime) &&
(repetitive || currentEvent != lastReportedEvent)) {
listener.actionPerformed(
new 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);
}
}