EDT是否有太多工作要做?

时间:2019-08-05 11:20:26

标签: java performance event-dispatch-thread

此样本不断绘制各种颜色的正方形。平方数基于JFrame的大小。

在执行示例时,使用鼠标放大或缩小尺寸框,它将增加或减少可见闪烁方块的数量。

帧的时间栏显示时间。此示例在draw()例程中还具有System.out.println。

目标不是要讨论此示例的编写水平如何,而是要用作提出问题的工具。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class LotsOfSquares  extends JPanel 
{

  Random rand = new Random();
  static JFrame frame = new JFrame("Lots Of Squares ");
  int numOfSquares = 0;

  public void paintComponent(Graphics g) 
  {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    int sizeOfSquare = 5;

    numOfSquares = 0;
    for (int x=0; x<frame.getSize().width; x = x + sizeOfSquare )
    {
        numOfSquares ++;
        for (int y=0; y<frame.getSize().height; y = y + sizeOfSquare )
        {
            g2d.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
            g2d.fillRect(x, y, sizeOfSquare, sizeOfSquare);
            numOfSquares ++;
            System.out.println("   Displaying " + numOfSquares + " squares within Inner Loop");
        }
    }
    //System.out.println("   Displaying " + numOfSquares + " squares total");
  }

  public static void main(String[] args) 
  {
LotsOfSquares  rects = new LotsOfSquares ();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(rects);
    frame.setSize(360, 300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    TimerTask repeatedTask = new TimerTask() 
    {
        public void run() 
        {
            //System.out.println("Task performed on " + new Date());
            frame.repaint();
        }
    };

    Timer timer = new Timer("Refresh Timer");
    long delay  = 1000L;
    long period = 150L;
    timer.scheduleAtFixedRate(repeatedTask, delay, period);


    TimerTask clockTask = new TimerTask() 
    {
        public void run() 
        {
         SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm:ss");
            Calendar currentCalendar = Calendar.getInstance();
            Date currentTime = currentCalendar.getTime();
            SwingUtilities.invokeLater(new Runnable() 
            {
              public void run()
              {
                  frame.setTitle(timeFormat.format(currentTime) );
              }
            });
          }
    };

    Timer clockTimer= new Timer("Clock Timer");
    long clockDelay  = 1000L;
    long clockPeriod = 1000L;
    clockTimer.scheduleAtFixedRate(clockTask, clockDelay, clockPeriod);
  }
}

程序启动时,框架很小,方框以恒定速率闪烁,时钟按时滴答滴答,并且System.out命令正在正常输出。

此示例最适合2-3个监视器。

随着框的扩展,闪烁方块的数量增加,并且开始缓慢闪烁得多,时钟开始跳数秒。

问题:

只需注释掉内部循环System.out调用:System.out.println(" Displaying " + numOfSquares + " squares within Inner Loop");,并删除注释就可以修改外部环路System.out调用:System.out.println(" Displaying " + numOfSquares + " squares total");

这告诉我,即使归因于代码编写方式,EDT也无法处理工作量。如果出现这种情况,是否有可能使眨眼变得平滑,并使时钟不跳动?

将EDT中的frame.setTitle(timeFormat.format(currentTime) );删除对于时钟来说效果很好,但是正方形仍然闪烁得更慢。

假设此示例满足应用程序要求,那么如何使正方形在大框架下闪烁(在小框架下闪烁)以及防止时钟跳秒呢?

您指出什么时候,应用程序只是在要求JVM和EDT做太多事情?

1 个答案:

答案 0 :(得分:2)

您可以在其他线程上绘制,然后将要绘制的图像传递到组件中。这样,您可以将工作分流到其他线程,从而使EDT不再执行繁重的任务。您可以使用多个线程来准备所需的图像,这取决于您。我通常就是这样处理需要大量功率才能获得更好帧速率的图形的。

在您的示例中,我将创建一些带有多个线程的Exacutor,并创建一些Future来为您创建BufferedImage,然后为执行器提供许多这些任务,并在您准备好BufferedImage传递给它时到要绘制的组件。这样,您可以拥有更好的性能。执行器中有多少个线程,或者什么时候向执行器提供新任务,这些都留给OP进行考虑。