怎样才能同样的计算产生不同的结果(How can same calculation produce

2019-10-21 05:54发布

只要花两个小时调试这一点,我想我知道了问题的原因,但我不明白它如何能产生一种它的结果。

我有一个基于Swing应用程序,我重写JPanel.paint(图形G)这样的

public void paint(Graphics g) {
    <snipped code>

    Insets is = getInsets();
    Dimension sz = getSize();
    g2.setClip(is.left + 1, is.top + 1, sz.width - is.right - is.left - 2, sz.height - is.top - is.bottom - 2);

    int w = getWidth();
    int h = getHeight();
    double s = Math.min(sz.getWidth(), sz.getHeight());

    AffineTransform mc = g2.getTransform();

    AffineTransform m1 = new AffineTransform(mc);
    m1.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
    m1.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
    m1.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));

    AffineTransform m2 = new AffineTransform(mc);
    m2.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
    m2.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
    m2.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));

    try {
        m_InverseViewTransform = m1.createInverse();
    } catch (NoninvertibleTransformException e) {

        AffineTransform m3 = new AffineTransform(mc);
        m3.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
        m3.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
        m3.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));

        System.out.println("m1 = " + m1);
        System.out.println("m2 = " + m2);
        System.out.println("m3 = " + m3);

        AffineTransform m4 = new AffineTransform(mc);
        System.out.println("m4 = " + m4);
        m4.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
        System.out.println("m4 = " + m4);
        m4.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
        System.out.println("m4 = " + m4);
        m4.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));
        System.out.println("m4 = " + m4);

        System.out.println(w); 
        System.out.println(h);
        System.out.println(s);
        System.out.println(m_CenterX);
        System.out.println(m_CenterY);
        System.out.println(m_ScaleX);
        System.out.println(m_ScaleY);

        e.printStackTrace();

现在,神秘,有时当我启动应用程序,往往不是,说三次出来的四,NoninvertibleTransformException被抛出。

正如你所看到调试I输出违规矩阵和其他三个相同的计算矩阵和用于形成这些矩阵的变量。

而这正是它有趣的,看到下面的输出,所有矩阵中不具有相同的价值!

m1 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m2 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m3 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m4 = AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
m4 = AffineTransform[[1.0, 0.0, -49.5], [0.0, 1.0, -0.362762953421903]]
m4 = AffineTransform[[5.254545454545455, 0.0, -260.1], [0.0, -587.9922126928986, 213.3017916655554]]
m4 = AffineTransform[[5.254545454545455, 0.0, 139.89999999999998], [0.0, -587.9922126928986, 502.3017916655554]]
800
578
578.0
49.5
0.36276295342190257
0.009090909090909092
1.0172875652126274
java.awt.geom.NoninvertibleTransformException: Determinant is 0
at java.awt.geom.AffineTransform.createInverse(AffineTransform.java:2706)

更有趣的东西,如果我适合移动调试输出/计算各地深入挖掘这个问题消失。

这种情况仅与jdk1.8.0_25.jdk JRE(在Mac OS X 10.8.5),不与Java 1.6或1.6。

好吧,我认为真正的罪魁祸首是JPanel的不是在事件分派线程创建的,一旦我这样做的例外是不会抛出没有任何不一致。

所以很显然是一个线程相关的时间依赖的问题,但我很好奇,怎么能这样呢,在Java的JVM“规则”所涉及的所有变量是本地的方法,并从该的AffineTransform矩阵方法不应该有副作用这么样很难让人理解线程的问题是如何导致这样的事情...

对于我的一片心意,我想明白是怎么回事。

作为一个副作用这个问题,可以帮助一些可怜的灵魂类似问题挣扎。

此外,如果有人设法针点那么明显缺陷的代码/调试/扣减我一直在这些线路现在盯着小时,我不介意。

Answer 1:

如果该方法不依赖于任何共享的数据,然后它不能表现出你描述的行为。 这是不是从你提出什么明确的,但是,你的方法避免了共享的数据。 我特别可疑的变量m_CenterXm_CenterYm_ScaleXm_ScaleY 。 这些闻起来像你的类的实例变量,如果这样的话,他们是实例化类和EDT线程之间共享的肯定。 缺席正确的同步,则可以EDT然后看到那些变量的默认值,它们由构造(或在另一个线程上调用其它方法)分配的值之前。

更一般地,通过在运行EDT方法直接或间接地访问类的任何实例变量是在EDT和在其中创建的对象(如果那些不同)的线程之间共享。



文章来源: How can same calculation produce different results