如何在Java Swing中实现空闲任务

我有一个GUI应用程序,变得非常慢。 我想开始介绍各种GUI任务的时间安排 – 但是,我们的许多GUI操作会触发其他操作,然后“稍后调用”以触发其他操作。

最终,这一切都安定下来,没有什么可做的了。 这时,我想停止计时器并报告GUI“动作”花了多长时间。

我认为这样做的方法是实现一个名为invokeOnceIdle(Runnable task) 。 只有在AWTEventQueue为“空”时,该方法才会执行提供的任务。 即提供的“任务”应该是队列中的最后一件事。

一种方法是,如果有办法为SwingUtilities.invokeLater指定“最低”优先级 – 但这是不可能的。

我接下来看看是否可以“invokeLater”一个Runnable来检查事件队列是否为“空” – 但是没有公开的方法来查看事件队列是否实际为空。

最好的方法是什么?

使用您自己的事件队列,您可以轻松实现该目标。 在这里,我做了一些东西,应该让你去:

 private static class MyEventQueue extends EventQueue { private Deque onceIdle = new LinkedList(); public MyEventQueue() { Toolkit.getDefaultToolkit().getSystemEventQueue().push(this); } public void runOnceIdle(Runnable toRun) { onceIdle.addLast(toRun); } @Override protected void dispatchEvent(AWTEvent event) { super.dispatchEvent(event); if (peekEvent() == null) { for (Runnable toRun : onceIdle) { toRun.run(); } onceIdle.clear(); } } } 

您所要做的就是使用runOnceIdle()将“Once idle”runnables推送到EventQueue的实例

isEventDispatchThread返回if当前AWTEventQueue是否为空,

  • 如果当前AWTEventQueue为空,您可以将新事件发布到EventQueue

invokeAndWait()invokeLater也是如此

  • 如果当前AWTEventQueue不为空则那么你不能只使用invokeAndWait() invokeLater()

例如

 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; } }