【问题标题】:How can I create synchronized methods across different classes and files?如何跨不同的类和文件创建同步方法?
【发布时间】:2011-04-03 22:57:55
【问题描述】:

我有多个文件和类。简而言之,一个人将计算一个粒子的位置,而另一个类移动粒子。我遇到的问题是在第一堂课完成计算之前粒子正在移动。我尝试使两种方法同步,但这似乎没有什么不同,是因为它们在不同的类中吗?最好的方法是什么?

编辑:我根本没有使用线程,它似乎在并行运行多个方法。

编辑 2:这是我的代码大纲

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
}

第二个文件

AllOtherParticles.java

public void checkIfTheyCollide(){
for(run through arrayList){
    //check if it collides with each point in array
}

public void drawCluster(){
//draws the cluster
}

【问题讨论】:

  • 同步(TheParticle){ ... }
  • 埃里克,这应该是一个答案,所以我可以投票:-)
  • 你的代码有bug,把代码贴出来。
  • 单个线程上的所有 java 调用都是同步的,即按顺序执行。同步锁适用于多个线程。所以唯一合乎逻辑的结论是你的代码有错误。
  • 啊……计时器在不同的线程上运行。阅读文档。一般来说,尽可能避免使用多个线程,这要困难得多。您可以让一个线程执行 Thread.sleep(time) 作为替代方案。

标签: java methods synchronized


【解决方案1】:

我尝试使这两种方法同步,但似乎没有什么不同,是因为它们属于不同的类吗?

是的,将同步修饰符添加到方法会在调用该方法的对象上同步。也就是说,

public synchronized void foo() {
    // code
}

等价于

public void foo() {
    synchronized (this) {
        // code
    }
}

由于方法驻留在不同的类中,this 引用不同的对象,因此您不会在两种方法中使用相同的锁。

解决当前问题的合理方法是:

class Particle {
    synchronized void setLocation(Location loc) {
        // code
    }

    synchronized Location getLocation() {
        return location;
    }
}

编辑:当然,这假设涉及多个线程。如果只有一个线程,synchronized 无效,因此无济于事。

【讨论】:

  • 调用 getLocation() 的方法会持有足够长的锁以完成对位置的所有计算吗?
  • 有没有办法在没有多线程的情况下模拟同步?
【解决方案2】:

我还不明白你为什么要使用线程,而不是一个简单的循环,在它的主体中使用许多类。

但也许循环障碍会帮助您解决线程问题,我还没有完全理解。

使用 Cyclic Barrier 可以让您例如在多个线程中从 1 计数到 100,确保一个线程永远不会比其他线程快 1 步。

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html

【讨论】:

  • 对不起,我不清楚。我没有使用多线程。看来我的程序同时运行了多个方法。
  • 如果你没有使用多线程,你的程序永远不会同时运行两个方法。只需使用 ecipe 的调试器来解决您的问题,请投票给我,因为我只需要 10+ 即可获得 250 =)
【解决方案3】:

在两个线程中同步您正在修改的对象。

synchronized (TheParticle) {
  // Move it
}


synchronized (TheParticle) {
  // Calculate on it
}

【讨论】:

  • 对象正在从其中的方法中移动。而计算是在不同类的方法中完成的。
  • @yousefrisco:你可以使用synchronized(this) { ... }
【解决方案4】:

假设这些方法不是同一个类上的方法,如果你简单地将它们声明为synchronized,它们将不会在同一个对象上同步。因此,您还没有实现互斥。

如果你想让两个不同的类在同一个对象上同步,你需要这样做:

public class Particle {
    public synchronized void foo() {
        // ... in critical region 
    }
}

public class Mover {
    public void bar() {
        ...
        synchronize (someParticle) {
            // ... in critical region 
        }
        ...
    }
}

请注意,这两种方法需要在同一个Particle 实例上同步synchronized 语句允许您在指定实例上同步,而不是在this 上同步。

【讨论】:

    【解决方案5】:

    我想我们可以在类上使用同步来实现两个不同资源之间的同步。 sn -p synchronized(X.class) 使用类实例作为监视器。看下面的代码和结果。如果我错了,请纠正我。

    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();
                }
            }
        }
    }
    

    }

    结果:

    Starting
    Done
    T1 Sleeping for 5 Sec
    T1 Waked up after 5 sec
    T2 Sleeping for 5 Sec
    T2 Waked up after 5 sec
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多