java多线程之wait(),notify(),notifyAll()的详解分析

所属分类: 软件编程 / java 阅读数: 48
收藏 0 赞 0 分享
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对象都有wait(),notify(),notifyAll()的功能.因为每个对象都有锁,锁是每个对象的基础,当然操作锁的方法也是最基础了。

wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或被其他线程中断。wait只能由持有对像锁的线程来调用。

notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程(随机)。直到当前的线程放弃此对象上的锁,才能继续执行被唤醒的线程。同Wait方法一样,notify只能由持有对像锁的线程来调用.notifyall也一样,不同的是notifyall会唤配所有在此对象锁上等待的线程。
"只能由持有对像锁的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj)之内.再者synchronized代码块内没有锁是寸步不行的,所以线程要继续执行必须获得锁。相辅相成。
看一个很经典的例子(生产者与消费者):
首先是消费者线程类:
复制代码 代码如下:

import java.util.List;
public class Consume implements Runnable {
 private List container = null;
 private int count;
 public Consume(List lst) {
  this.container = lst;
 }
 public void run() {
  while (true) {
   synchronized (container) {
    if (container.size() == 0) {
     try {
      container.wait();// 容器为空,放弃锁,等待生产
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    container.remove(0);
    container.notify();
    System.out.println("我吃了" + (++count) + "个");
   }
  }
 }
}

接下来是生产者线程类:
复制代码 代码如下:

import java.util.List;
public class Product implements Runnable {
 private List container = null;
 private int count;
 public Product(List lst) {
  this.container = lst;
 }
 public void run() {
  while (true) {
   synchronized (container) {
    if (container.size() > MultiThread.MAX) {
     // 如果容器超过了最大值,就不要在生产了,等待消费
     try {
      container.wait();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    container.add(new Object());
    container.notify();
    System.out.println("我生产了" + (++count) + "个");
   }
  }
 }
}

最后是测试类:
复制代码 代码如下:

import java.util.ArrayList;
import java.util.List;
public class MultiThread {
 private List container = new ArrayList();
 public final static int MAX = 5;
 public static void main(String args[]) {
  MultiThread m = new MultiThread();
  new Thread(new Consume(m.getContainer())).start();
  new Thread(new Product(m.getContainer())).start();
 }
 public List getContainer() {
  return container;
 }
 public void setContainer(List container) {
  this.container = container;
 }
}

运行结果如下所示:
复制代码 代码如下:

我生产了1个
我吃了1个
我生产了2个
我生产了3个
我生产了4个
我生产了5个
我生产了6个
我生产了7个
我吃了2个
我生产了8个
我吃了3个
我生产了9个
我吃了4个
我吃了5个
我吃了6个
我吃了7个
我吃了8个
我生产了10个
我生产了11个
我吃了9个
我生产了12个
我吃了10个
......

更多精彩内容其他人还在看

SpringBoot SpEL语法扫盲与查询手册的实现

这篇文章主要介绍了SpringBoot SpEL语法扫盲与查询手册的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Java创建子线程的两种方法

这篇文章主要介绍了Java创建子线程的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Boot2.x集成JPA快速开发的示例代码

这篇文章主要介绍了Spring Boot2.x集成JPA快速开发,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

关于Java中的mysql时区问题详解

这篇文章主要给大家介绍了关于Java中mysql时区问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

JAVA参数传递方式实例浅析【按值传递与引用传递区别】

这篇文章主要介绍了JAVA参数传递方式,结合实例形式分析了java按值传递与引用传递区别及相关操作注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中MessageDigest来实现数据加密的方法

这篇文章主要介绍了Java中MessageDigest来实现数据加密的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

spring 注解验证@NotNull等使用方法

这篇文章主要介绍了spring 注解验证@NotNull等使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

浅谈如何优雅地停止Spring Boot应用

这篇文章主要介绍了浅谈如何优雅地停止Spring Boot应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Python如何使用@property @x.setter及@x.deleter

这篇文章主要介绍了Python如何使用@property @x.setter及@x.deleter,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java Jmeter全局变量设置过程图解

这篇文章主要介绍了Java Jmeter全局变量设置过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多