我正在尝试制作一个方法,可以从初始参考帧到质心帧进行转换。 方法中使用的集合包含许多对象,其中包括质量,位置和速度(如果有帮助)。
/**
* 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。
答案 0 :(得分:1)
Particle类没有equals和hashCode的显式实现(我没有做任何事情:/),你的意思是我不能修改HashSet中的Objects参数吗?
Java Set强制执行元素的唯一性。添加的每个对象都与现有对象进行比较,以确保它不重复。
HashSet使用对象的hashCode
和equals
方法执行此操作,询问它们是否彼此相同。您可以修改HashSets中对象的字段,但是您不能修改在计算hashCode或测试相等性时使用的任何字段,因为这会破坏/混淆该集合。
由于您没有覆盖hashCode
和equals
方法,因此默认实现只是测试对象“identity”:这是同一个对象吗?在这种情况下,两个具有相等值的已创建对象将被视为单独的,并且两者都可以添加到单个HashSet中。由于甚至没有查看字段,因此您可以安全地修改任何字段而不会破坏集合。
所以看起来HashSet随机发出了元素。这是正常的吗?
是。 HashSet不保证元素的顺序,并且订单甚至不会保持稳定。 (在内部,它通过hashCodes的一些位来对对象进行排序,给出难以预测且有效的随机顺序。当一个集增长时,它开始查看hashCodes的更多位以有效地确定唯一性,导致它们随机重新排列再次。)如果你真的需要强制执行Set的顺序,你可以使用LinkedHashSet代替。
但是,使用Set可能会在您的应用程序中浪费精力。使用List和ArrayList代替Set和HashSet。 List更简单,并保证可预测的迭代顺序:元素按添加顺序迭代。 List也比Set快,因为它不会花费太多努力来防止相同的对象被添加两次。
也不知道什么是多线程,所以我不太可能这样做。
作为一个简单的类比,线程是一个遍历代码的指令指针。 (想象一下,手指指向当前正在执行的代码行。)这是通过方法,语句,循环等执行它们的步骤。你总是至少有一个线程,否则你的程序根本就不会运行。您可以创建任意数量的线程并将它们设置为一次运行在您的程序中。在多CPU系统上,这些线程可以真正同时执行,每个CPU上一个。但是,您还可以拥有比CPU更多的线程,在这种情况下,CPU将轮流执行线程(每10毫秒左右更改为一个不同的线程),使它们看起来是同步的。
为什么添加印刷品会使其更加系统化?
我能想到的唯一原因是您正在修改多个线程的共享数据。线程基本上彼此视而不见,我的意思是它们自然不会尝试合作。这会导致两个问题:(1)如果两个线程同时尝试更改数据,则数据可能会被破坏并最终导致某个线程的值不正确; (2)线程可能不会注意到另一个线程是否已经更改了某些变量,因为任何线程都可以假设变量具有它们先前由该线程设置的相同值。
为了使多线程安全,有必要在线程之间共享的任何更改数据周围添加一些synchronization。
如果在没有同步的情况下从多个线程使用您的粒子集,则该集可能会被破坏,和/或某些值的更改不会被其他线程看到。添加print语句的效果是它访问共享的,正确同步的资源(输出到控制台的流),因此它会导致执行打印的线程之间的发生之前关系,从而确保先前的更改看到了,它修复了问题(2),虽然它是显式同步的非常草率的替代品。
您可能无意中使用了多个线程。例如,创建图形用户界面会创建一个用于处理输入事件的线程。从那时起,您应该切换到该线程并对其执行所有程序的工作,或者围绕任何共享的更改数据添加同步。
如果你确定你没有编辑多个线程的数据,我看不出print语句可能会有什么不同。 (也许它没有什么区别,唯一的混乱是关于HashSet稳定性的错误假设。)
答案 1 :(得分:0)
您可能在线程之间存在内存可见性问题。打印恰好在输出流上进行同步,从而创建内存屏障并与屏蔽问题的主内存同步。