线程之间对于资源锁状态进行通讯时的wait,notify方法
wait,notify,notifyAll都是Object类的方法,用于线程之间对于资源锁状态进行通讯;
重点:wait,notify,notifyAll这几个方法必须在synchronized即有锁状态下调用,任何对象上调用这些方法的当前线程都应该具有对象监视器,否则它将抛出java.lang.IllegalMonitorStateException
保证你调用的wait、notify ,notifyAll的对象,是你synchronized 的对象。
1.wait
调用wait会立刻释放synchronized(obj)中的obj锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放),调用wait方法的一个或多个线程就会解除wait状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运行。
wait():
Causes the current thread to wait until another thread invokes the {@link java.lang.Object#notify()} method or the {@link java.lang.Object#notifyAll()} method for this object.
导致当前线程等待,直到另一个线程调用此对象的{@link java.lang.Object#notify()}方法或{@link java.lang.Object#notifyAll()}方法。
wait(long millis) :
Causes the current thread to wait until either another thread invokes the {@link java.lang.Object#notify()} method or the {@link java.lang.Object#notifyAll()} method for this object, or a specified amount of time has elapsed.
导致当前线程等待,直到其他线程调用该对象的{@link java.lang.Object#notify()}方法或{@link java.lang.Object#notifyAll()}方法,或者已经经过了指定的时间。
测试代码:(部分)
@Override
public void run() {
super.run();
System.out.println("thread1");
System.out.println(this.getState());
System.out.println(this.getThreadGroup().getName());
Log.i("cyp", "run: "+this.getThreadGroup().activeCount());
synchronized (object) {
try {
object.wait(10000);
System.out.println("Thread1 wait 方法执行后");
sleep(10000);
System.out.println("Thread1 sleep方法结束");
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结:
object.wait(10000),首先释放object锁
这10秒时间内,此线程不会去抢锁,即使object锁空闲也不会抢,10秒后开始抢锁,抢到锁执行object.wait(10000)之后的代码;
注意:sleep(10000)方法不释放锁,锁还是在此线程,sleep10秒后,继续之后sleep后面的代码;
2.notify
代码:
class Test2Runnable implements Runnable{
private static final String TAG = "cyp";
private LockObject lockObject;
public Test2Runnable(LockObject lockObject) {
this.lockObject = lockObject;
}
@Override
public void run() {
synchronized (lockObject) {
lockObject.notify();
Log.i(TAG, "run: Test2Runnable 还在运行");
}
}
}
执行完 lockObject.notify();方法后,没有释放锁lockObject,继续执行输出“run: Test2Runnable 还在运行”,执行完synchronized 代码块里的代码后,才会释放锁lockObject,等待该锁lockObject的其中一个线程(执行了wait的线程)被唤醒,抢到锁lockObject后,执行对应线程里面的代码;
notifyAll()方法:
class Test2Runnable implements Runnable{
private static final String TAG = "cyp";
private LockObject lockObject;
public Test2Runnable(LockObject lockObject) {
this.lockObject = lockObject;
}
@Override
public void run() {
synchronized (lockObject) {
lockObject.notifyAll();
Log.i(TAG, "run: Test2Runnable 还在运行");
}
}
}
同样的代码,notify换成notifyAll,此时会唤醒所有执行了lockObject .wait的等待线程,它们随机的去抢锁,先抢到线程先执行,但是被唤醒的所有的lockObject .wait的等待线程,都会有机会抢到锁执行代码,目前我创建的测试线程,是如下:
只在run方法中加了一个wait方法
@Override
public void run() {
// synchronized 使用范围
synchronized (lockObject) {
try {
Log.i("cyp", "test1Runnable:synchronized ");
Log.i("cyp","test1Runnable wait 方法执行前"+Thread.currentThread().getName()+",state:"+Thread.currentThread().getState());
lockObject.wait();
Log.i("cyp", "test1Runnable wait 方法执行后"+Thread.currentThread().getName()+",state:"+Thread.currentThread().getState());
Thread.sleep(10000);
// lockObject.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
创建线程代码如下:
Test1Runnable runnable = new Test1Runnable(lockObject);
one = new Thread(runnable);
one.setName("线程one");
one.setPriority(10);
one.start();
Test1Runnable runnable1 = new Test1Runnable(lockObject);
Thread three = new Thread(runnable1);
three.setName("线程three");
three.setPriority(1);
three.start();
Test1Runnable runnable2 = new Test1Runnable(lockObject);
Thread four = new Thread(runnable2);
four.setPriority(5);
four.setName("线程4");
four.start();
当这些线程都进入wati状态后,我通过点击事件出发notifyAll,"线程4"先抢到锁执行,随后"线程one","线程three“相继执行;
总结.notify()或notifyAll()方法调用后,线程不会立即释放锁,只会将wait中的线程从等待队列移到同步队列,也就是线程状态从waitting变为blocked;
notifyAll执行后,被唤醒的所有的同一个对象wait的线程,抢到锁的顺序和优先级关系不大,只能锁优先级高的线程被优先唤醒的机率大些;