1

免責事項: このコードは、静的および非静的メソッドの同期ブロックからコピーされています

私はそれにいくつかの変更を加えました。同期された静的メソッドと非静的メソッドの両方をスレッドに呼び出す方法を知りたいです。非静的メソッドを同期ブロックにラップすることで機能させることができます。他に方法はありますか?

public class StaticNonStaticSynch  
{ 
 public static void main(String[] args)  
 { 
      final StaticNonStaticTest staticNonStaticTest = new StaticNonStaticTest(); 
  Runnable runnable1 = new Runnable()  
  { 
   @Override 
   public void run()  
   { 
staticNonStaticTest.nonStaticMethod(); 
   } 
  }; 

  Runnable runnable2 = new Runnable()  
  { 
   @Override 
   public void run()  
   { 
    StaticNonStaticTest.staticMethod(); 
   } 
  }; 

  Thread thread1 = new Thread(runnable1, "First Thread"); 
  Thread thread2 = new Thread(runnable2, "Second Thread"); 

  thread1.start(); 
  thread2.start(); 
 } 
} 

class StaticNonStaticTest 
{ 

 void nonStaticMethod() 
 { 
 //synchronized (StaticNonStaticTest.class){ 
   for(int i=0;i<50;i++) 
   { 
    System.out.println("Non - Static method called by " + Thread.currentThread().getName() +" : = "+i); 
   } 
// } 
 } 
 static synchronized void staticMethod() 
 {  
   for(int i=0;i<50;i++) 
   { 
    System.out.println("Static method called by " + Thread.currentThread().getName() +" : = "+i); 
   } 
 } 
} 
4

2 に答える 2

4

これを覚えておいてください:

public class MyClass {

    public synchronized void doSomething() {
        // Do something
    }

    public synchronized static void doSomethingStatic() {
        // Do something static
    }
}

基本的にこれにコンパイルされます:

public class MyClass {

    public void doSomething() {
        synchronized(this) {
            // Do something
        }
    }

    public static void doSomethingStatic() {
        synchronized(MyClass.class) {
            // Do something static
        }
    }
}

それらは同じもので同期しないことに注意してください。これを修正するには、両方がロックするオブジェクト(相互に排他的なオブジェクトまたは「ミューテックス」と呼ばれます)を作成します。

public class MyClass {

    private static final Object MUTEX = new Object();

    public void doSomething() {
        synchronized(MUTEX) {
            // Do something
        }
    }

    public static void doSomethingStatic() {
        synchronized(MUTEX) {
            // Do something static
        }
    }
}

これにより、これら2つのメソッドの1つだけが複数のスレッドで同時に実行されるようになります。

いくつかのヒント:

  • 常にそれで使用synchronized(variable)してvariableくださいfinal
  • MUTEX厳密にミューテックスである必要はなく、実際のオブジェクトである可能性があります。以下の例を参照してください。
  • synchronizedメソッドの修飾子がどのように効果的に実装されているかを覚えておいてください。またはのsynchronizedブロックのようなものです。thisMyClass.class

厳密にミューテックスであるオブジェクトを持つことに加えて、である任意のフィールドを使用できますfinal。たとえば、Map反復中に同期するには、次のようにします。

public class MyClass {

    private static final Map<String, String> map = new HashMap<String, String>(); // Java 6
    private static final Map<String, String> map = new HashMap<>(); // Java 7

    public static void put(String k, String v) {
        synchronized(map) {
            map.put(k, v);
        }
    }

    public static void printAll() {
        synchronized(map) {
            for (Entry<String, String> entry : map.entrySet()) {
                System.out.println(entry.getKey() + ":" + entry.getValue());
            }
        }
    }
}

このコードは、あなたが決して得ないことを保証しますConcurrentModificationException

于 2012-10-24T23:20:37.733 に答える
2

両方のメソッドを共通のロック オブジェクトで内部的に同期させることができます。それ以外の場合、静的メソッドの実行中にインスタンス メソッドをブロックする唯一の方法は、クラス オブジェクトで同期することです (コメント行にあるように)。

同期インスタンス メソッドは、オブジェクト インスタンスで同期します。同期された静的メソッドは、クラス インスタンスで同期します。クラスのインスタンスが 2 つある場合 (たとえば、異なるクラス ローダーから)、同期された静的メソッドが同時に実行される可能性があることに注意してください。これを実現するにはかなりの作業を行う必要があるため、通常、これが発生しているかどうかはわかります。

共通のロック オブジェクトで静的メソッドとインスタンス メソッドの両方を同期する 1 つの方法を次に示します。

class StaticNonStaticTest {
    private static final Object LOCK_OBJECT = new Object();

    void nonStaticMethod() {
        synchronized (LOCK_OBJECT) {
            for (int i=0; i<50; i++) {
                System.out.println("Non - Static method called by "
                  + Thread.currentThread().getName() + " : = " + i);
            }
        }
    }

    static void staticMethod() {
        synchronized (LOCK_OBJECT) {
            for (int i=0; i<50; i++) {
                System.out.println("Static method called by "
                  + Thread.currentThread().getName() +" : = "+i);
            } 
        } 
    }
}
于 2012-10-24T22:31:49.877 に答える