Как я могу создать синхронизированные методы для разных классов и файлов? - PullRequest
2 голосов
/ 04 апреля 2011

У меня есть несколько файлов и классов.Проще говоря, один будет выполнять вычисления одного местоположения частицы, в то время как другой класс перемещает частицу.У меня проблема в том, что частица перемещается до того, как первый класс закончен с вычислениями.Я попытался сделать оба метода синхронизированными, но это, похоже, не изменило их, потому что они в разных классах?Какой лучший способ сделать это?

РЕДАКТИРОВАТЬ: я вообще не использую потоки, просто кажется, что он выполняет несколько методов параллельно.

РЕДАКТИРОВАТЬ 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
}

Ответы [ 5 ]

1 голос
/ 04 апреля 2011

Я пытался синхронизировать оба метода, но, похоже, они не различались, потому что они в разных классах?

Да, добавление синхронизированного модификатора в методсинхронизируется на объекте, на котором вызывается метод.То есть

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 не имеет никакого эффекта и, следовательно, не поможет.

1 голос
/ 04 апреля 2011

Синхронизируйте объект, который вы изменяете, в обоих потоках.

synchronized (TheParticle) {
  // Move it
}


synchronized (TheParticle) {
  // Calculate on it
}
1 голос
/ 04 апреля 2011

Я пока не понимаю, почему вы используете потоки вообще, а не простой цикл, используя много классов в его теле.

Но, возможно, Cyclic Barrier поможет вам использовать ваши проблемы с многопоточностью, которые я до сих пор не понял полностью.

Использование циклического барьера позволяет вам, например, считать от 1 до 100 в нескольких потоках, гарантируя, что один никогда не будет более чем на 1 шаг быстрее, чем другие потоки.

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

0 голосов
/ 14 декабря 2016

Полагаю, мы можем использовать синхронизацию в классе для достижения синхронизации между двумя различными ресурсами. Синхронизированный фрагмент (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
0 голосов
/ 04 апреля 2011

Предполагая, что методы не являются методами одного и того же класса, если вы просто объявите их как 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...