java - EDT 是否可能有太多工作?

标签 java performance event-dispatch-thread

该示例不断绘制各种颜色的方 block 。方 block 的数量取决于 JFrame 的大小。

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

该帧的时间栏显示时间。此示例的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);
  }
}

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

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

随着框架的扩展,闪烁方 block 的数量会增加,并且开始闪烁得更慢,并且时钟开始跳秒。

问题:

简单地注释掉内部循环 System.out 调用:System.out.println(" Displaying " + numOfSquares + " squares within Inner Loop");并删除外循环 System.out 调用的注释:System.out.println(" Displaying " + numOfSquares + " squares total");取得了显着的进步。

这告诉我,即使归因于代码的编写方式,EDT 也根本无法处理工作负载。如果出现这样的情况,是否可以平滑闪烁并使时钟不跳动?

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

假设此示例满足应用程序要求,如何才能使大框架下的方 block 像小框架下一样闪烁,并防止时钟跳秒?

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

最佳答案

您可以在其他线程上绘图,然后将生成的图像传递到组件中进行绘制。通过这种方式,您可以将工作卸载到其他线程,从而使 EDT 免于执行繁重的任务。您可以使用多个线程来准备所需的图像,这取决于您。这是我通常处理需要大量电量才能获得更好帧速率的绘图的方式。

在您的示例中,我将创建一些具有多个线程的 Exacutor,并创建一些为您创建 BufferedImage 的 Future,然后您向执行器提供许多这样的任务,当您准备好 BufferedImage 时,将其传递给执行器到要绘制的组件。这样你就能有更好的表现。执行器中有多少个线程,或者何时向执行器提供新任务,都留给 OP 考虑。

关于java - EDT 是否可能有太多工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57357536/

相关文章:

java - 发行: Creating a very accurate Swing Timer

java - java中compareTo方法返回什么

javascript - 将数组合并为一个

performance - Pandas to_excel-如何使其更快

java - JTextArea默认值?

java - GUI 未正确更新,组件消失

java - 当我尝试创建 Opengl ES 环境时,我的应用程序不断崩溃

c# - 如何在文件上的 C# 和 Java 之间读取/写入无符号字节数组?

java - 在同一对象中测试方法时如何模拟对象中的方法

python - 高效查询字段范围内缺失的整数?