调用静态和非静态方法的线程

时间:2012-10-24 22:28:32

标签: java multithreading

免责声明:此代码是从synchronized blocks for static and non-static methods

复制的

我对它做了一些修改。我想知道如何使线程调用同步静态和非静态方法。我可以通过将非静态方法包装在同步块中来使其工作。还有其他办法吗?

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

2 个答案:

答案 0 :(得分: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
        }
    }
}

请注意,他们不会在同一件事上同步。要解决此问题,请为它们两者创建一个对象以锁定(称为互斥对象,或者#34;互斥体&#34;):

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
        }
    }
}

这应该使得这两个方法中只有一个在多个线程中同时运行。

一些提示:

  • 始终在synchronized(variable)上使用variable final
  • MUTEX并非必须严格来说是互斥锁,它可能是一个实际的对象。请参阅下面的示例。
  • 请记住如何有效实施方法上的synchronized修饰符。它就像synchronizedthis上的MyClass.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

答案 1 :(得分:2)

您可以让两个方法在公共锁定对象上进行内部同步。否则,在静态方法执行时使实例方法块的唯一方法是在类对象上进行同步(就像在注释行中一样)。

同步实例方法在对象实例上同步; synchronized静态方法在类实例上同步。请注意,如果有两个类实例(例如,来自不同的类加载器),则同步静态方法可能会同时执行。你通常会知道这是否正在发生,因为你必须做大量工作才能实现。

这是在公共锁定对象上同步静态和实例方法的一种方法:

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