在下面的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();
}
});
}
}
答案 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);