2017-01-26 13 views
1

私はgoalSpeedとcurrentSpeedを持つオブジェクトRotorを持っています。それぞれが現在のSpeedSpeedをgoalSpeedの設定に合わせて変更しようとします。私は4つの別々のスレッドを実行しているこれらのローターの4つを持っています。各自がコントローラによって定期的に新しいgoalSpeedを割り当てられます。オブジェクトの複数のインスタンスを同期させました

私はそれぞれの回転子で現在のスピードを変更しようとすると、すべての回転子の現在のスピードの合計を超えることはできません。 > X.

ここに私の問題があります:ロータの現在の速度を上げることができるかどうかを確認するとき、私はスピード条件の合計。しかし、このチェックの直後に、各ロータが別のスレッドで別のスレッドが別のスレッドに変更されている可能性があります。したがって、他のスレッドでの私のチェックはもう有効ではありません。 1つのローターのsetNewSpeed()メソッドで他のローターが現在の速度を変更しないことを確認するにはどうすればよいですか?

class Rotor implements Runnable { 
    private int id; 
    private int goalSpeed; 
    private int currentSpeed; 
    private Controller controller; 
    private int Y; 
    private int failedAttempts; 
    private int successAttempts; 
    private int maxSpeed; 

    public int getSuccessAttempts() { 
     return successAttempts; 
    } 

    public void setSuccessAttempts(int successAttempts) { 
     this.successAttempts = successAttempts; 
    } 

    public int getMaxSpeed() { 
     return maxSpeed; 
    } 

    public void setMaxSpeed(int maxSpeed) { 
     this.maxSpeed = maxSpeed; 
    } 

    public int getFailedAttempts() { 
     return failedAttempts; 
    } 

    public Rotor(Controller c, int Y, int id){ 
     this.controller = c; 
     this.Y = Y; 
     this.id = id; 
     this.currentSpeed = 0; 
     this.failedAttempts = 0; 
     this.goalSpeed = 0; 
     this.maxSpeed = 0; 
     this.successAttempts = 0; 
    } 

    synchronized public void setGoalSpeed(int s){ 
     this.goalSpeed = s; 
    } 

    public int getCurrentSpeed(){ 
     return currentSpeed; 
    } 

    synchronized private void setNewSpeed(){ 
     int currentDrain = 0; 
     for(Rotor r : controller.getRotors()){ 
      currentDrain = currentDrain + r.getCurrentSpeed(); 
     } 
     if((currentDrain + (goalSpeed - currentSpeed)) > 20){ 
      //we cannot increase by total amount because drain too high 
      System.out.println("failed"); 
      this.failedAttempts++; 
      currentSpeed = currentSpeed + (20 - currentDrain); 
      System.out.println("currentSpeed:" + currentSpeed); 
     } else { 
      System.out.println("success"); 
      successAttempts++; 
      currentSpeed = goalSpeed; 
     } 
//  System.out.println("goalSpeed:" + goalSpeed); 
//  System.out.println("currentDrain:" + currentDrain); 

} 

    public void run() { 
     try { 
      while(true){ 
       setNewSpeed(); 
       if(currentSpeed > maxSpeed){ 
        maxSpeed = currentSpeed; 
       } 

       Thread.sleep(Y); 
      } 
     } catch (InterruptedException e) { 
      System.out.println("Rotor " + id + ": checks=" + (int)(successAttempts + failedAttempts) + ", success rate=" + successAttempts + ", failedAttempts=" + failedAttempts + ", max=" + maxSpeed); 
     } 
    } 
} 

答えて

1

すべてのロータ間で共有されるロックを同期させます。それぞれが独自のロック(つまり、this)で同期しているので、メソッドが同期されていても、同時に別のオブジェクトで呼び出すことができます。

0

すべてを同期させる最も簡単な方法は、static synchronizedメソッドを使用することです。つまり、インスタンス間で共有される明示的なロックオブジェクトを使用するほうがよいでしょう。あなたが規則と基準を尊重したい場合は、

synchronized private void setNewSpeed()

synchronized public void setGoalSpeed(int s)が、private synchronized void setNewSpeed()public synchronized void setGoalSpeed(int s)を書くべきではありません

+0

彼は、静的メソッドからインスタンスのプロパティにアクセスすることはできません。 – Kayaman

+0

@ Kayamanしかし、彼はパラメータでインスタンスを渡してから、プライベートメソッドまたは渡されたインスタンスのプライベートメンバーにアクセスすることができます。 –

+0

確かに彼がデザインを回していれば。 – Kayaman

0

1)。

2)Rotor Runnableクラスで2つの同期メソッドを宣言しますが、同期メソッドではスレッド間で共有されるデータを操作しないため意味がありません。

3)問題を解決する方法は複数あります。
フレキシブルな解決策は、setNewSpeed()メソッドを呼び出すときに、スレッド間で共有される人工オブジェクトを使用し、このオブジェクトに対してロックを実行することです。
setNewSpeed()に入る前に、各トレッドがロックが解除されるのを待つことができます。ここで


は、ソリューションを実装するためのアイデアです:

  • Rotorをインスタンス化する前に、このような方法で共有オブジェクトを作成します。

    Object lockObject = new Object();

  • 変更public Rotor(Controller c, int Y, int id)public Rotor(Controller c, int Y, int id, Object lockObject)

  • Rotorのコンストラクタを呼び出し、Rotorsのすべてに対して同じlockObjectインスタンスを追加して、速度の変更を同期させます。

  • ロータ本体のフィールドとしてlockObjectをコンストラクタ本体に格納します。 Rotor

  • は、この方法で同期を行うためにlockObjectを使用します。

サンプルコード:

private void setNewSpeed(){ 
    synchronized(lockObject){ 
     ... your actual processing 
     } 
} 
関連する問題