为什么子线程中的synchronized方法持有主线程的锁定

时间:2014-06-23 07:40:20

标签: java android multithreading

我有一个同步方法。然后我将启动一个长时间操作的线程,子线程也有一个synchronized方法,但子线程中的synchronized方法将保持同步方法的锁定,这将导致我的应用程序。

我的代码是:

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

2 个答案:

答案 0 :(得分:1)

这是同步方法的标准行为。

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

  

对两个同步方法的调用是不可能的   相同的对象交错。当一个线程正在执行同步时   对象的方法,调用synchronized的所有其他线程   同一个对象块的方法(暂停执行)直到第一个   线程是用对象完成的。

所以代码

public synchronized void method() { 
} 

相当于

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

出于您的目的,您应该为connectToServerrestart方法使用不同的锁定对象

UPD。对不起,我错过了,你的方法是静态的。在这种情况下specification 8.4.3.6

  

synchronized方法在执行之前获取监视器。   对于类(静态)方法,使用与方法类的Class对象关联的监视器。

所以你不能同时运行一个类的两个同步方法,即使它们是静态的

答案 1 :(得分:0)

  

阻止主UI线程5秒或更长时间会导致ANR。

来自Anr Message with synchronized method

可能因为:

而发生了
Thread.sleep(20000); 

避免锁定主UI线程。