I have multiple files and classes. To put it simply, one will run calculations one the location of a particle while another class moves the particle. The problem I'm having is that the particle is being moved before the first class is finished with the calculations. I tried making both methods synchronized but that didn't seem to make a different, is it because they are in different classes? What's the best way to do this?
EDIT: I am not using threads at all, it just seems that it's running multiple methods in parallel.
EDIT 2: Here's an outline of my code
MovingParticle.java
public int x, y;
public void shootParticle(){
//move particle and change x, y values
//this method is called by a timer
}
public void drawParticle(){
//draws the particle
}
Second file
AllOtherParticles.java
public void checkIfTheyCollide(){
for(run through arrayList){
//check if it collides with each poi开发者_JAVA技巧nt in array
}
public void drawCluster(){
//draws the cluster
}
I tried making both methods synchronized but that didn't seem to make a different, is it because they are in different classes?
Yes, adding the synchronized modifier to a method synchronizes on the object the method is invoked on. That is,
public synchronized void foo() {
// code
}
is equivalent to
public void foo() {
synchronized (this) {
// code
}
}
Since the methods reside in different classes, this
refers to different objects, and you are therefore not using the same lock in both methods.
A reasonable way to solve your immediate problem would be to do:
class Particle {
synchronized void setLocation(Location loc) {
// code
}
synchronized Location getLocation() {
return location;
}
}
Edit: Of course, that assumes more than one thread is involved. If there's only one thread, synchronized
has no effect and thus won't help.
I do not get yet why you are using threads at all, instead of a simple loop, using many classes in it's body.
But maybe the Cyclic Barrier will help you using your Threading problems, which I did not understand yet completely.
Using a Cyclic Barrier allows you e.g. to count up from 1 to 100 in multiple threads, ensuring one is never more than 1 step faster than the other threads are.
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html
Synchronize on the object you're modifying in both threads.
synchronized (TheParticle) {
// Move it
}
synchronized (TheParticle) {
// Calculate on it
}
Assuming that the methods are not methods on the same Class, if you simply declare them as synchronized
they won't synchronize on the same object. Hence you haven't implemented mutual exclusion.
If you want two different classes to synchronize on the same object, you need to do something like this:
public class Particle {
public synchronized void foo() {
// ... in critical region
}
}
public class Mover {
public void bar() {
...
synchronize (someParticle) {
// ... in critical region
}
...
}
}
Note that the two methods need to synchronize on the same Particle
instance. The synchronized
statement allows you to synchronize on a specified instance, rather than on this
.
I guess we can use synchronization on class to achieve synchronization between two different resources. The snippet synchronized(X.class) uses the class instance as a monitor. Look at the following code and result. Correct me if I am wrong.
public class SyncTest1 {
public static void main(String[] args) {
System.out.println("Starting");
SyncTest1 syncTest1 = new SyncTest1();
Resource r1 = syncTest1.new Resource();
Resource1 r2 = syncTest1.new Resource1();
Runnable runnable = new Runnable() {
@Override
public void run() {
r1.printThread("T1");
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
r2.printThread("T2");
}
};
new Thread(runnable).start();
new Thread(runnable2).start();
System.out.println("Done");
}
private class Resource {
public void printThread(String threadName) {
synchronized (String.class) {
try {
System.out.println(threadName + " Sleeping for 5 Sec");
Thread.sleep(5000);
System.out.println(threadName + " Waked up after 5 sec");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private class Resource1 {
public void printThread(String threadName) {
synchronized (String.class) {
try {
System.out.println(threadName + " Sleeping for 5 Sec");
Thread.sleep(5000);
System.out.println(threadName + " Waked up after 5 sec");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Result:
Starting
Done
T1 Sleeping for 5 Sec
T1 Waked up after 5 sec
T2 Sleeping for 5 Sec
T2 Waked up after 5 sec
精彩评论