sleep() 和 wait() 有什么区别?
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,
给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。
调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,
进入等待此对象的等待锁定池,
只有针对此对象发出notify方法(或notifyAll)
后本线程才进入对象锁定池准备获得对象锁进入运行状态。
wait() 与 notify() 和 notifyAll()
wait():令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当
前线程排队等候其他线程调用notify()或notifyAll()方法唤醒,唤醒后等待重新获得对监视器的所有
权后才能继续执行。
notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
notifyAll ():唤醒正在排队等待资源的所有线程结束等待.
这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报
java.lang.IllegalMonitorStateException异常。
因为这三个方法必须有锁对象调用,而任意对象都可以作为synchronized的同步锁,
因此这三个方法只能在Object类中声明。
wait() 方法
在当前线程中调用方法: 对象名.wait()
使当前线程进入等待(某对象)状态 ,直到另一线程对该对象发出 notify
(或notifyAll) 为止。
调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)
调用此方法后,当前线程将释放对象监控权 ,然后进入等待
在当前线程被notify后,要重新获得监控权,然后从断点处继续代码的执行。
notify()/notifyAll()
在当前线程中调用方法: 对象名.notify()
功能:唤醒等待该对象监控权的一个/所有线程。
调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)
代码:
/**
* 生产者消费者问题
* 分析:
* 1.是否是多线程问题:是,存在生产者线程,消费者线程
* 2.是否有共享数据:是,店员,商品
* 3.如何解决线程安全问题:同步代码块,同步锁,lock锁
* 4.是否涉及线程通信问题。是
* @author sun
* @date 2021/7/16 - 16:21
*/
public class ProductTest {//测试
public static void main(String[] args) {
Clerk clerk = new Clerk();
Thread Producterthread = new Thread(new Producter(clerk));
Thread Consumerthread = new Thread(new Consumer(clerk));
Producterthread.start();
Consumerthread.start();
}
}
class Clerk{//售货员
private int product=0;
public synchronized void addProduct(){//添加产品
if (product>=20){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
product++;
System.out.println("生产者生产了第"+product+"个产品");
notifyAll();//唤醒正在排队等待资源的所有线程结束等待
}
}
public synchronized void getProduct(){//售出产品
if (this.product<=0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("消费者取走了第"+product+"个产品");
product--;
notifyAll();
}
}
}
class Producter implements Runnable{//生产者
Clerk clerk;
public Producter(Clerk clerk){
this.clerk=clerk;
}
public void run() {
System.out.println("生产者开始生产产品");
while (true){
try {
Thread.sleep((int)Math.random()*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.addProduct();
}
}
}
class Consumer implements Runnable{//消费者
Clerk clerk;
public Consumer (Clerk clerk){
this.clerk=clerk;
}
public void run() {
System.out.println("消费者开始取走产品");
while (true) {
try {
Thread.sleep((int) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.getProduct();
}
}
}