Java没有提供稳定的输出

时间:2014-03-22 04:48:09

标签: java hashset

我正在尝试制作一个方法,可以从初始参考帧到质心帧进行转换。 方法中使用的集合包含许多对象,其中包括质量,位置和速度(如果有帮助)。

    /**
 * Method used to set origin at the Center of Mass (COM) of the system. This
 * method calculates position(r) and velocity(v) of the COM in initial
 * frame, then uses them to transform v and r of each particle in the system
 * to COM frame.
 * 
 * @param astroObjSet
 *            a set containing massive particles
 */
private static void COM(Set<Particle> astroObjSet) {
    // temporary variables used in the method
    Vector velSum = new Vector();// Sum of velocities multiplied by mass
    Vector posSum = new Vector();// Sum of position multiplied by mass
    double totalMass = 0;

    // this loop calculates total mass of the given system, sum of v_i*m_i,
    // and sum of r_i*m_i for each particle i in the system

    for (Particle element : astroObjSet) {

        totalMass = totalMass + element.getMass();

        velSum = Vector.add(velSum,element.getVelocity().times(element.getMass()));

        posSum = Vector.add(posSum,element.getPosition().times(element.getMass()));

    }

    // calculate COM velocity and position in initial frame of reference
    Vector COMpos = posSum.times(1 / totalMass);
    Vector COMvel = velSum.times(1 / totalMass);

    // transform position and velocity of each particle in the set to COM
    // frame of reference.
    for (Particle element : astroObjSet) {


        Vector finPos = new Vector(Vector.Subtract(element.getPosition(),
                COMpos));
        Vector finVel = new Vector(Vector.Subtract(element.getVelocity(),
                COMvel));

        element.setPosition(finPos);
        element.setVelocity(finVel);
    }

但是出于某种原因,除非我将println("String")放在方法的某个地方,否则方法只会有十分之一的时间(我甚至算过)。如果在调用方法之前或之后放置println("String")它也可以,但不是没有。基本上一切都只有在我检查时才有效。从未想过量子力学会在Java中追捕我。

有人知道发生了什么事吗?

更新1 修正了求和循环,感谢Boann。

2 个答案:

答案 0 :(得分:1)

  

Particle类没有equals和hashCode的显式实现(我没有做任何事情:/),你的意思是我不能修改HashSet中的Objects参数吗?

Java Set强制执行元素的唯一性。添加的每个对象都与现有对象进行比较,以确保它不重复。

HashSet使用对象的hashCodeequals方法执行此操作,询问它们是否彼此相同。您可以修改HashSets中对象的字段,但是您不能修改在计算hashCode或测试相等性时使用的任何字段,因为这会破坏/混淆该集合。

由于您没有覆盖hashCodeequals方法,因此默认实现只是测试对象“identity”:这是同一个对象吗?在这种情况下,两个具有相等值的已创建对象将被视为单独的,并且两者都可以添加到单个HashSet中。由于甚至没有查看字段,因此您可以安全地修改任何字段而不会破坏集合。

  

所以看起来HashSet随机发出了元素。这是正常的吗?

是。 HashSet不保证元素的顺序,并且订单甚至不会保持稳定。 (在内部,它通过hashCodes的一些位来对对象进行排序,给出难以预测且有效的随机顺序。当一个集增长时,它开始查看hashCodes的更多位以有效地确定唯一性,导致它们随机重新排列再次。)如果你真的需要强制执行Set的顺序,你可以使用LinkedHashSet代替。

但是,使用Set可能会在您的应用程序中浪费精力。使用ListArrayList代替Set和HashSet。 List更简单,并保证可预测的迭代顺序:元素按添加顺序迭代。 List也比Set快,因为它不会花费太多努力来防止相同的对象被添加两次。

  

也不知道什么是多线程,所以我不太可能这样做。

作为一个简单的类比,线程是一个遍历代码的指令指针。 (想象一下,手指指向当前正在执行的代码行。)这是通过方法,语句,循环等执行它们的步骤。你总是至少有一个线程,否则你的程序根本就不会运行。您可以创建任意数量的线程并将它们设置为一次运行在您的程序中。在多CP​​U系统上,这些线程可以真正同时执行,每个CPU上一个。但是,您还可以拥有比CPU更多的线程,在这种情况下,CPU将轮流执行线程(每10毫秒左右更改为一个不同的线程),使它们看起来是同步的。

  

为什么添加印刷品会使其更加系统化?

我能想到的唯一原因是您正在修改多个线程的共享数据。线程基本上彼此视而不见,我的意思是它们自然不会尝试合作。这会导致两个问题:(1)如果两个线程同时尝试更改数据,则数据可能会被破坏并最终导致某个线程的值不正确; (2)线程可能不会注意到另一个线程是否已经更改了某些变量,因为任何线程都可以假设变量具有它们先前由该线程设置的相同值。

为了使多线程安全,有必要在线程之间共享的任何更改数据周围添加一些synchronization

如果在没有同步的情况下从多个线程使用您的粒子集,则该集可能会被破坏,和/或某些值的更改不会被其他线程看到。添加print语句的效果是它访问共享的,正确同步的资源(输出到控制台的流),因此它会导致执行打印的线程之间的发生之前关系,从而确保先前的更改看到了,它修复了问题(2),虽然它是显式同步的非常草率的替代品。

您可能无意中使用了多个线程。例如,创建图形用户界面会创建一个用于处理输入事件的线程。从那时起,您应该切换到该线程并对其执行所有程序的工作,或者围绕任何共享的更改数据添加同步。

如果你确定你没有编辑多个线程的数据,我看不出print语句可能会有什么不同。 (也许它没有什么区别,唯一的混乱是关于HashSet稳定性的错误假设。)

答案 1 :(得分:0)

您可能在线程之间存在内存可见性问题。打印恰好在输出流上进行同步,从而创建内存屏障并与屏蔽问题的主内存同步。