调用线程的sleep,yield方法时,线程并不会让出对象锁,wait却不同。
wait函数必须在同步代码块中调用(也就是当前线程必须持有对象的锁),他的功能是这样的:
我累了,休息一会儿,对象的锁你们拿去用吧,CPU也给你们。
调用了wait函数的线程会一直等待,直到有其他线程调用了同一个对象的notify或者notifyAll方法才能被唤醒,需要注意的是:被唤醒并不代表立即获得对象的锁。也就是说,一个线程调用了对象的wait方法后,他需要等待两件事情的发生:
才能继续往下执行后续动作。
如果一个线程调用了某个对象的wait方法,但是后续并没有其他线程调用该对象的notify或者notifyAll方法,则该线程将会永远等下去…
notify/notifyAll方法也必须在同步代码块中调用(也就是调用线程必须持有对象的锁),他们的功能是这样的:
女士们,先生们请注意,锁的对象我即将用完,请大家醒醒,准备一下,马上你们就能使用锁了。
不同的是,notify方法只会唤醒一个正在等待的线程(至于唤醒谁,不确定!),而notifyAll方法会唤醒所有正在等待的线程。还有一点需要特别强调:调用notify和notifyAll方法后,当前线程并不会立即放弃锁的持有权,而必须要等待当前同步代码块执行完才会让出锁。
如果一个对象之前没有调用wait方法,那么调用notify方法是没有任何影响的。
下面来看一个例子:
package com.cooperation;
import java.util.concurrent.TimeUnit;
public class Test
{
public static Object object = new Object();
static class Thread1 implements Runnable
{
@Override
public void run()
{
synchronized(object)
{
System.out.println(Thread.currentThread().getName()+" is running.");
try
{
object.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" get the lock.");
}
}
}
static class Thread2 implements Runnable
{
@Override
public void run()
{
synchronized(object)
{
System.out.println(Thread.currentThread().getName()+" is running.");
object.notify();
System.out.println(Thread.currentThread().getName()+" invoke notify()");
System.out.println(Thread.currentThread().getName()+" release the lock.");
}
}
}
public static void main(String[] args) throws InterruptedException
{
Thread thread1 = new Thread(new Thread1());
Thread thread2 = new Thread(new Thread2());
thread1.start();
TimeUnit.SECONDS.sleep(1);
thread2.start();
}
}Thread-0 is running. Thread-1 is running. Thread-1 invoke notify() Thread-1 release the lock. Thread-0 get the lock.
可以看到当Thread-0调用了wait方法后就释放了object锁,Thread-1获取锁之后调用notify的释放锁,但是这个时候Thread没有立刻获取object锁,而是等到了Thread-1的同步块退出之后才获取了object的锁。
如果将class Thread2中的 System.out.println(Thread.currentThread().getName()+" release the lock.");这句放在synchronized(object)的外面,有可能出现如下的运行结果:
Thread-0 is running. Thread-1 is running. Thread-1 invoke notify() Thread-0 get the lock. Thread-1 release the lock.
这是因为,当Thread-1释放了object锁并且退出了同步块之后Thread-0立刻获取了锁,而这时候两个线程的打印语句的顺序就随机了。
JAVA线程间协作:wait.notify.notifyAll
原文:http://blog.csdn.net/u013256816/article/details/50440123