报错log:
2019-04-11 17:03:43.799 13792-13808/? E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.pipiyang.cn03, PID: 13792
java.lang.IllegalMonitorStateException: object not locked by thread before notify()
at java.lang.Object.notifyAll(Native Method)
at com.example.getphoneapplication.WaitTest$1.run(WaitTest.java:32)
调用地方的写法:
WaitTest waitTest = new WaitTest();
Log.d("xinyu2",waitTest.getString());
有问题的类的写法:
package com.example.getphoneapplication;
/**
* =======================================================================================
* 作 者:caoxinyu
* 创建日期:2019/4/11.
* 类的作用:
* 修订历史:
* =======================================================================================
*/
public class WaitTest {
private boolean mloaded = false;
private final Object mlock = new Object();
public WaitTest() {
loadFromDisk();
}
private void loadFromDisk() {
new Thread(){
@Override
public void run() {
synchronized (WaitTest.this){
super.run();
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mloaded = true;
notifyAll();
}
}
}.start();
}
public String getString(){
synchronized (WaitTest.this){
while (!mloaded) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return "success";
}
return "";
}
}
}
没有问题的类的写法1
package com.example.getphoneapplication;
/**
* =======================================================================================
* 作 者:caoxinyu
* 创建日期:2019/4/11.
* 类的作用:
* 修订历史:
* =======================================================================================
*/
public class WaitTest {
private boolean mloaded = false;
private final Object mlock = new Object();
public WaitTest() {
loadFromDisk();
}
private void loadFromDisk() {
new Thread(){
@Override
public void run() {
synchronized (WaitTest.this){
super.run();
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mloaded = true;
WaitTest.this.notifyAll();
}
}
}.start();
}
public String getString(){
synchronized (WaitTest.this){
while (!mloaded) {
try {
WaitTest.this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return "success";
}
return "";
}
}
}
没有问题的类的写法2
package com.example.getphoneapplication;
/**
* =======================================================================================
* 作 者:caoxinyu
* 创建日期:2019/4/11.
* 类的作用:
* 修订历史:
* =======================================================================================
*/
public class WaitTest {
private boolean mloaded = false;
private final Object mlock = new Object();
public WaitTest() {
loadFromDisk();
}
private void loadFromDisk() {
new Thread(){
@Override
public void run() {
synchronized (WaitTest.this){
super.run();
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
doLoad();
}
}
}.start();
}
private void doLoad() {
mloaded = true;
notifyAll();
}
public String getString(){
synchronized (WaitTest.this){
while (!mloaded) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return "success";
}
return "";
}
}
}
原因:
在匿名内部类里面调用notify,调用的是这个匿名内部类的notify,而这个匿名内部类是没有被synchronized的。
第一种方法修改后:
把doLoad 提取到整个类里面,这个时候调用的就不是匿名内部类的notifyAll 了。而是WaitTest 的notifyAll();
private void doLoad() {
mloaded = true;
notifyAll();
}
第二种修改方法,是调用 WaitTest.this.notifyAll();
总结:
要保证你调用的notify 的对象,是你synchronized 的对象。
我说查看android 源码SharedPreferencesImpl 他的写法没有问题,而我的写法有问题,是因为他提取了方法到主类里面,调用的是主类的notify。 简单的提取方法,是有坑的。提取方法也会产生问题。