1. wait()、notify()、notifyAll()方法是由Object类提供的方法,且都被声明为final,所以无法重新定义它们。通过这3个方法您可以要求线程进入等待,或者是通知线程回到Runnable状态。
2. 必须在被同步化的方法或区块中调用wait()方法,当对象的wait()方法被调用时,当前的线程会被放入对象的等待集合(Wait Set)中,线程会解除对对象的锁定,其他的纯种可竞争执行被同步化区块。被放在等待集合中的线程将不参与线程的排队,wait()可以指定等待的时间,如果指定时间,则时间到之后线程会再度加入排队,如果指定时间为0或者不指定,则线程会持续等待,直到被中断,或是被告知参与排队。
3. 当对象的notify()被调用时,它会从当前对象的等待集中通知一个线程加入排队。被通知的线程是随机的,被通知的线程会与其他正在执行的线程共同竞争对对象的锁定。如果调用notifyAll(),则所有在等待集中的线程都会被通知加入排队,这些线程会与其他正在执行的线程共同竞争对对象的锁定。
4.当线程调用到对象的wait()方法时,表示它要先让出对象的被同步区使用权并等待通知,或是等待一段指定的时间,直到被通知或时间到时再与其他线程竞争。如果可以执行时应从等待点开始执行。
5.生产者消费者实例:生产者--店员--消费者。店员一次只能拥有固定数量的产品,若生产者生产了过多的产品,店员叫生产者等一下,如果店中有空位放产品了再通知生产者继续生产,如果店中没有产品了,店员会告诉消费者等一下,如果有产品了再通知消费者来取走产品。
package ysu.hxy;
/*
* 店员类
*
*/
public class Clerk
{
//-1表示目前没有产品
private int product = -1;
//这个方法由生产者调用
public synchronized void setProduct(int product)
{
if(this.product != -1)
{
try
{
//目前店员没有空间收产品,请稍候!
wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
this.product = product;
System.out.printf("生产者设定(%d)%n",this.product);
//通知等待区中的一个消费者可以继续工作了
notify();
}
//这个方法由消费者调用
public synchronized int getProduct()
{
if(this.product == -1)
{
try
{
//缺货了,请稍候
wait();
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
int p = this.product;
System.out.printf("消费者取走(%d)%n",this.product);
this.product = -1;
//通知等待区中的一个生产者可以继续工作了
notify();
return p;
}
}
package ysu.hxy;
public class Producer implements Runnable
{
private Clerk clerk;
public Producer(Clerk clerk)
{
this.clerk = clerk;
}
public void run()
{
System.out.println("生产者开始生产整数......");
//生产1到10的整数
for(int product = 1;product <= 10;product++)
{
try
{
//暂停随机时间
Thread.sleep((int)Math.random() * 3000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//将产品交给店员
clerk.setProduct(product);
}
}
}
package ysu.hxy;
public class Consumer implements Runnable
{
private Clerk clerk;
public Consumer(Clerk clerk)
{
this.clerk = clerk;
}
public void run()
{
System.out.println("消费者开始消耗整数......");
//消耗10个整数
for(int i=1;i<=10;i++)
{
try
{
//等待随机时间
Thread.sleep((int)Math.random()*3000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//从店员处取走整数
clerk.getProduct();
}
}
}
下面编写范例来测试生产者、消费者与店员的行为。
package ysu.hxy;
public class ProductTest
{
public static void main(String[] args)
{
Clerk clerk = new Clerk();
//生产者线程
Thread producerThread = new Thread(new Producer(clerk));
//消费者线程
Thread consumerThread = new Thread(new Consumer(clerk));
producerThread.start();
consumerThread.start();
}
}
执行结果如下:
D:\hxy>java ysu.hxy.ProductTest
生产者开始生产整数......
消费者开始消耗整数......
生产者设定(1)
消费者取走(1)
生产者设定(2)
消费者取走(2)
生产者设定(3)
消费者取走(3)
生产者设定(4)
消费者取走(4)
生产者设定(5)
消费者取走(5)
生产者设定(6)
消费者取走(6)
生产者设定(7)
消费者取走(7)
生产者设定(8)
消费者取走(8)
生产者设定(9)
消费者取走(9)
生产者设定(10)
消费者取走(10)
生产者会生产10个整数,而消费者会消耗10个整数。由于店员处只能放置一个整数,所以只能每生产一个就消耗一个。
如果一个线程进入对象的等待集中,可以中断它的等待,这时将会发生InterruptedException异常。可以使用线程对象的interrupt()方法来中断等待的动作。
分享到:
相关推荐
Java 同步方式 wait和notify/notifyall
wait和notify讲解
JAVAWAIT和NOTIFY的用法.pdf
java-wait和notify的用法.pdf
开一个子线程来完成一个循环处理的工作,我在主线程中能灵活控制这个子线程的开始、暂停/继续、结束。
Java多线程的样例代码,工程,内含wait()、notify()和sychronized的使用范例。
使用Java多线程的wait和notify方法实现最简单的生产者消费者模式
wait()、notify()和notifyAll()方法1---马克-to-win java视频
java中多线程编程notify、wait的使用
一个理解wait()与notify()的例子,让你更好理解.
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
3(深入理解Wait、Notify和Wait与sleep区别).rar
主要介绍了Java wait和notify虚假唤醒,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
java多线程下wait和notify的作用
java多线程之wait,notify的用法([ 详解+实例 ]).
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify 和 notifyAll 来实现...
主线程去控制子线程wait与notify
本篇文章是对java多线程wait()和notify()进行了详细的分析介绍,需要了解的朋友参考下
源码—Java多线程5—死锁和wait notify notifyAll
wait,notify等线程知识.pdf