首先你的概念不是很清楚。被声明为synchronized的方法里不一定要有notify方法。
synchronized表示该程序段为排他访问的,是解决代码冲突问题的。比如:
有两个进程同时(或先后)对同一方法提出访问,而该方法中有排他的要求就必须加上synchronized字段。
wait和notify、notifyall是为了控制共享对象的访问的,典型的例子是生产者和消费者的例子:(该例子也用了synchronized)
生产者生产的产品要放到仓库中,消费者从仓库中取产品去消费,而仓库的容量是有限的。生产者在生产一个产品放到仓库中前要判断仓库是否已满,如果已满则要wait()仓库对象,消费者取走一个产品时要notify仓库对象。而对仓库容量的增减语句段就是synchronized的了。
synchronized表示该程序段为排他访问的,是解决代码冲突问题的。比如:
有两个进程同时(或先后)对同一方法提出访问,而该方法中有排他的要求就必须加上synchronized字段。
wait和notify、notifyall是为了控制共享对象的访问的,典型的例子是生产者和消费者的例子:(该例子也用了synchronized)
生产者生产的产品要放到仓库中,消费者从仓库中取产品去消费,而仓库的容量是有限的。生产者在生产一个产品放到仓库中前要判断仓库是否已满,如果已满则要wait()仓库对象,消费者取走一个产品时要notify仓库对象。而对仓库容量的增减语句段就是synchronized的了。
throws InterruptedException
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
引起当前线程等待,进入队列。直到另一个线程调用对象的notify或者notifyAll方法。此方法的功能相当于仅仅执行了wait(0)方法。
----------------------------------------------------------------------
public final void notify()
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.
唤醒队列中的一个线程。
如果当前线程调用wait的话,仅仅说明当前线程进入队列。只有当两个方法一起使用的话,例如先notify再wait,才说明,当前线程让位于队列中线程,且自己再次进入队列,但是当它调用notify完毕后,它已经不是当前线程了,所以,在一个synchronized方法中,一个线程不可能一次完成先notify后wait的动作。
那如果是先wait再notify呢?你想想,也是不可能的。那么在一次操作里,一个线程要么只完成notify,要么只完成wait。可是,为什么有的synchronized方法里有,有的没有呢?
wait()方法使该同步对象锁死,而notify释放这个同步对象的lock.而notify释放的lock没有指向性,如果同时有几个lock,则有JVM选择其中一个来释放,而notifyall可以释放所有的lock.因此需优先使用notifyall.另外,你可以参考practical java一书,这本书对于多线程有很好的解释.
调用wait()方法会使当前线程进入等待池,但要注意的是等待池是与某个具体对象有关的,而不是所有线程都在一个等待池中。
调用notify()方法或notifyAll()方法是对某个具体对象使用的,notify()方法会释放该对象的等待池中的一个线程,notifyAll()方法会释放该对象的等待池中的所有对象。但要注意的是某个线程调用过notify()方法或notifyAll方法后不一定会“让位”也会继续执行的。
sychronized()方法与wait()、notify()、notifyAll()没有必然的联系,你为什么非要把他们联系到一起考虑呢?
必须在该方法执行完成之后才能在其他的线程中执行!!
既然“某个线程调用过notify()方法或notifyAll方法后不一定会“让位”也会继续执行的”,那么为什么还要调用notify等方法唤醒等待池中的线程呢?-----------------------------------唤醒的目的是让别人进来,既然自己都没有出去,别人还怎么进来呢?
1、notifyAll固然能释放某对象等待池中所有线程,但是这所有线程还是只有一个进入临界区啊,那么为什么还要释放等待池中所有线程,而不只释放一个线程,更有甚者,还有人说优先使用notifyAll,优先使用还有个什么劲呀???
答:在notifyAll()之后,释放了N个线程,但并不是N-1个线程会返回等待池,只要能满足N个线程中的M个线程执行的条件,那么这M个线程都会执行的。“临界区”并不是等待池,sychronized的临界区某一时刻只有一个线程在,但和等待对象可用不是一个概念。例如消费者和生产者例子,如果生产者一次能生产3个产品而消费者一次消费1个产品,那么如果仓库对象为空造成的消费者在等待池中等待,而生产者的notifyAll()调用会使3个消费者线程执行,而其它消费者线程继续等待。但在3个消费者线程去执行“仓库容量减1”这个操作时一定要sychronized,你懂了吗?
2、既然“某个线程调用过notify()方法或notifyAll方法后不一定会“让位”也会继续执行的”,那么为什么还要调用notify等方法唤醒等待池中的线程呢?
答:这个问题就更不对了,调用notify()方法的线程和被唤醒的线程完全可以同时运行啊?
同情中,这个确实很难弄懂,你可以看看如下的例子:
本例子实现了两个线程,每个线程输出1到100的数字。
第一个线程输出1-10,停止,通知第二个线程 输出1-10 第二个线程停止 通知第一个线程 输出11-20 ...
实现的要点是
在Java中,每个对象都有个对象锁标志(Object lock flag)与之想关联,当一个线程A调用对象的一段synchronized代码时,
它首先要获取与这个对象关联的对象锁标志,然后执行相应的代码,执行结束后,把这个对象锁标志返回给对象;因此,在线程A执行
synchronized代码期间,如果另一个线程B也要执行同一对象的一段synchronized代码时(不一定与线程A执行的相同),它将
要等到线程A执行完后,才能继续....如何利用wait() notify() notifyAll()?在synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁标志,进入等待状态,并且可以调用notify()或者
notifyAll()方法通知正在等待的其他线程。notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程。
package jdeveloper.study;/**
* Title: Jdeveloper's Java Projdect
* Description: n/a
* Copyright: Copyright (c) 2001
* Company: soho http://www.ChinaJavaWorld.com
* @author [email protected]
* @version 1.0
*/
import java.lang.Runnable;
import java.lang.Thread;public class DemoThread implements Runnable{ public DemoThread() {
TestThread testthread1 = new TestThread(this,"1");
TestThread testthread2 = new TestThread(this,"2"); testthread2.start();
testthread1.start();
} public static void main(String[] args) {
DemoThread demoThread1 = new DemoThread(); }
public void run(){ TestThread t = (TestThread) Thread.currentThread();
try{
if (!t.getName().equalsIgnoreCase("1")) {
synchronized(this) {
wait();
}
}
while(true){ System.out.println("@time in thread"+ t.getName()+ "="+ t.increaseTime()); if(t.getTime()%10 == 0) {
synchronized(this) {
System.out.println("****************************************");
notify();
if ( t.getTime()==100 ) break;
wait();
}
}
}
}catch(Exception e){e.printStackTrace();}
}}class TestThread extends Thread{
private int time = 0 ;
public TestThread(Runnable r,String name){
super(r,name);
}
public int getTime(){
return time;
}
public int increaseTime (){
return ++time;
}
}