2014-06-23 92 views
0

我有一個同步方法。那麼我將用長時間操作啓動一個Thread,子線程也有一個同步方法,但是在子線程中的synchronized方法將保持synchronized方法的鎖定,這將導致anr在我的應用中。爲什麼在子線程中同步方法保持主線程鎖定

我的代碼是:

import java.util.Date; 

public class ThreadTest { 

    static MQTTThread mThread; 

    public static void main(String[] args) { 
     for (int i = 0; i < 100; i++) { 
      System.out.println("the " + i + " - restart time = " 
        + new Date()); 
      restart(i); 
     } 
    } 

    private static synchronized void restart(int i) { 
     System.out.println("the " + i + " - restart excute " + new Date()); 
     if (null != mThread) { 
      if (!mThread.isAlive()) { 
       try { 
        System.out 
        .println("Action:restartConnectThread in mThread.runFlag)"); 

        mThread = new MQTTThread(); 
        mThread.setName("MQTTThread"); 
        mThread.start(); 
        // mqttExecutor.execute(mThread); 
       } catch (Exception e) { 
        System.out.println("!mThread.runFlag"); 
       } 
      } else { 
       System.out.println("Action:restartConnectThread - CONNECTING"); 
      } 
     } else { 
      try { 
       System.out 
       .println("Action:restartConnectThread in null thread"); 
       mThread = new MQTTThread(); 
       mThread.setName("MQTTThread"); 
       mThread.start(); 
      } catch (Exception e) { 
       System.out.println("null mThread"); 
      } 
     } 
    } 

    private static class MQTTThread extends Thread { 
     public void run() { 

      connectToServer(); 
      System.out.println("connected"); 
     } 
    } 

    public static synchronized void connectToServer() { 
     try { 
      System.out.println("Thread.sleep " + new Date()); 
      Thread.sleep(20000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

運行代碼的結果是: – user3766493

+0

把它放在你的問題。不在評論中。 – awksp

+0

你可以在你打電話的地方寫出原始的android代碼嗎? – carlosvin

回答

1

這是synchronized方法標準行爲。

http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

它不可能的 同一對象的同步方法來交錯兩個調用。當一個線程正在爲一個對象執行一個同步的 方法時,所有其他線程調用同一個對象塊的同步方法 直到第一個線程與該對象完成爲止 。

所以代碼

public synchronized void method() { 
} 

相當於

public void method() { 
    synchronized (this) { 
    } 
} 

你的目的,你應該爲connectToServerrestart方法

UPD使用不同的鎖定對象。對不起,我錯過了,你的方法是靜態的。在這種情況下,specification 8.4.3.6

一個同步方法在它執行之前獲取一個監視器。 對於類(靜態)方法,使用與方法類的Class對象關聯的監視器。

所以你不能同時運行一個類的兩個synchronized方法,即使是靜態