wait:告诉线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify为止
notify:唤醒同一对象监视器中调用wait的第一个线程,用于类似饭馆有一个空位后通知所有等候就餐顾客中的第一位可以入座的情况.
notifyAll:唤醒同一对象监视器中调用wait的所有线程,具有最高优先级的线程首先被唤醒并执行.
看下面的步骤:
Thread t --> synchronized(o)--->o.wait()--->o.notify
1、新建一个线程t
2、线程t得到对象o的lock旗标
3、此时线程t被放置在对象o的等待线程池中,t自动释放o的锁旗标
4、当另外的线程执行了对象o的notify()方法后,线程t可能会被从o的等待线程池中释放出来,并且移动到等待线程对象o的锁旗标的线程池中,当t得到锁旗标时就会执行下去
下面是一个经典的消费者-生产者的线程间访问的代码举例
生产者的类如下:
class Producer implements Runnable
{
Q q;
public Producer(Q q)
{
this.q = q;
}
public void run()
{
int i = 0;
while(true)
{
if(i == 0 )
q.put("zhangsan","male");
else
q.put("lisi","female");
i = (i+1)%2;
}
}
}
消费者的类如下:
class Consumer implements Runnable
{
Q q;
public Consumer(Q q)
{
this.q = q;
}
public void run()
{
while(true)
{
q.get();
}
}
}
下面是用户信息的类,最经典的用法,各类有各类应该的职责,put()与get()方法写得很不错,值得学习
class Q
{
private String name="unknown";
private String sex = "unknown";
private boolean bFull = false;
public synchronized void put(String name,String sex)
{
if(bFull)
try{wait();} catch(Exception e){}
this.name = name;
try{Thread.sleep(1);} catch(Exception e){}
this.sex = sex;
bFull = true;
notify();
}
public synchronized void get()
{
if(!bFull)
try{ wait(); }catch(Exception e){}
System.out.print(name);
System.out.println(":" +sex);
bFull = false;
notify();
}
}
简单的运行类如下:
public class ThreadCommuncation
{
public static void main(String[] args)
{
Q q = new Q();
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
}
}
注明:文中所有的代码均为[张孝祥JAVA视频教程中的代码,并非我本人所写,我记录下来,只是复习一下线程间的一些关键点的地方.