与Java 6相比,Java 8的GUI性能较差

时间:2015-01-20 13:41:45

标签: java performance swing user-interface java-8

在下面的Java 6中,代码按预期运行,但在Java 8中,它需要花费更多的时间。有趣的是,组件使用相同的方法setEnable()来启用和禁用组件,但禁用调用所需的时间比启用组件要长得多,几乎是后者的两倍。 Java 8中的禁用时间比Java 1.6中的禁用时间长。问题是为什么会发生这种情况?这是Java 8的性能问题吗?

以下是Java 6的结果:

    Sun Microsystems Inc. 1.6.0_45
    Initializing GUI
    GUI initialized in 1105 ms
    Disabling
    Disabled in 687 ms
    Enabling
    Enabled in 375 ms

以下是Java 8的结果:

    Oracle Corporation 1.8.0_25
    Initializing GUI
    GUI initialized in 604 ms
    Disabling
    Disabled in 6341 ms
    Enabling
    Enabled in 370 ms

代码:

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class TestGUI extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;

    public TestGUI() {
        initGUI();
    }

    public void actionPerformed(ActionEvent e) {
        String text;
        if(e.getActionCommand().equals("Enable-ALL")){
            enableAll();
            text= "Disable-ALL";
        }
        else{
            disableAll();
            text= "Enable-ALL";
        }
        ((JButton)e.getSource()).setText(text);
        ((JButton)e.getSource()).setEnabled(true);

    }


    private  void initGUI() {
        long m = System.currentTimeMillis();
        System.out.println("Initializing GUI");
        setTitle(System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
        setLayout(new FlowLayout());

        JButton b = new JButton("Disable-ALL ");
        b.addActionListener(this);
        add(b);

        for (int i = 1; i < 10001; i++) {
            b = new JButton("Button " + i);
            add(b);
        }
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 600);
        setVisible(true);
        m = System.currentTimeMillis() - m;
        System.out.println("GUI initialized in " + m + " ms");
    }

    private void disableAll() {
        long m = System.currentTimeMillis();
        System.out.println("Disabling");
        for (Component c : getContentPane().getComponents()) {
            c.setEnabled(false);
        }

        m = System.currentTimeMillis() - m;
        System.out.println("Disabled in " + m + " ms");
    }

    private void enableAll() {
        long m = System.currentTimeMillis();
        System.out.println("Enabling");
        for (Component c : getContentPane().getComponents()) {
            c.setEnabled(true);
            invalidate();
        }
        m = System.currentTimeMillis() - m;
        System.out.println("Enabled in " + m + " ms");
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                System.out.println(System.getProperty("java.vendor") + " "
                        + System.getProperty("java.version"));
                new TestGUI();
            }
        });
    }
}

2 个答案:

答案 0 :(得分:25)

根据我的分析器,该操作大部分时间都花在方法Thread.holdsLock上,这可能确实是一项代价高昂的操作,由Component.checkTreeLock调用,Component.updateCursorImmediately间接调用}。

通常,您可以在操作之前调用getContentPane().setVisible(false);并在之后调用getContentPane().setVisible(true);来更新多个组件,从而避免代价高昂的可视更新,例如

private void disableAll() {
    long m = System.currentTimeMillis();
    System.out.println("Disabling");
    getContentPane().setVisible(false);
    for (Component c : getContentPane().getComponents()) {
        c.setEnabled(false);
    }
    getContentPane().setVisible(true);

    m = System.currentTimeMillis() - m;
    System.out.println("Disabled in " + m + " ms");
}

你会看到,无论哪种视觉更新导致问题的详细解决,这些问题都会消失。

所以你不需要考虑如何在这里正确地进行基准测试,而不是在操作需要几秒钟时重要,但我建议学习System.currentTimeMillis()System.nanoTime()之间的区别,因为后者是测量经过时间的正确工具

答案 1 :(得分:5)

我还没有机会完全理解,但似乎事件处理可能在8中发生了变化。首先禁用父母加速了这个过程:

getContentPane().setEnabled(false);
for (Component c : getContentPane().getComponents()) {
    c.setEnabled(false);
}
getContentPane().setEnabled(true);