正在运行的程序称作一个进程,一个进程可以包含多个线程,这些线程可以共享进程的资源,它们共用一块存储空间。那么,各个线程在访问同一个数据对象的同时,可能引起冲突,以生产者、消费者为例,就会出现队列中没有产品的情况下,消费者扔到队列中去拿产品,与现实世界中逻辑不相符合。使用synchronized关键字可以确保线程的安全运行。

  synchronized(obj){
.......
  obj.wait()/notifyAll();//是数据对象而不是线程调用wait和notifyAll方法
  }

  当给一个线程(比如A线程)的run方法体内加入上述代码时,说明A线程必须首先获得该数据对象的锁,才能对这个对象进行操作。A线程拿到这个obj数据对象的锁以后,在它释放以前任何其它线程都不能够操作此对象了,之所以这样,我们可以认为其它线程没有这把锁的钥匙。A线程执行obj.wait()方法后,它将释放其所占有的对象锁,A线程进入阻塞状态,同时A也就不具有了获得obj对象所的权力,这样其它线程就可以拿到这把锁了。obj.notifyAll()可以唤醒因obj对象而阻塞的所有线程,并允许它们有获得对象所的权力,obj.notify()是唤醒因obj对象而阻塞的任意一个线程。

  下面的程序模仿生产者和消费者:  

public class WaitAndNotify {
private static List<Double> queue;
public WaitAndNotify(){
queue = new ArrayList<Double>();
} public void begin(){
Thread producer = new Thread(){
public void run(){
while(true){
synchronized(queue){
double time = 1.0d;
long startTime = System.currentTimeMillis();
if(System.currentTimeMillis()-startTime>=time){
startTime =System.currentTimeMillis();
for(int i=0;i<10;i++){
queue.add((Math.random()*10000));
}
queue.notifyAll();
}
}
}
}
};
producer.start(); Thread consumer = new Thread(){
public void run(){
while(true){
synchronized(queue){
while(queue.isEmpty()){
System.out.println("队列的长度为:"+queue.size());
try {
queue.wait();
} catch (InterruptedException ex) {
Logger.getLogger(WaitAndNotify.class.getName()).log(Level.SEVERE, null, ex);
}
}
double result = queue.remove(0);
System.out.println("成功从队列中取到数据!"+result);
}
}
}
};
consumer.start();
} public static void main(String[] args){
WaitAndNotify obj = new WaitAndNotify();
queue.add(0.1231d);
obj.begin();
}
}

  producer线程向queue中放入数据,并掉调用queue.notifyAll()来唤醒所有阻塞的线程,consumer线程从queue中取数据,当没有数据时该线程就会进入阻塞状态,等待呗唤醒。

最新文章

  1. Create Volume 操作(Part I) - 每天5分钟玩转 OpenStack(50)
  2. FW: Chef集中管理工具实践之 (1) 环境部署
  3. 深入理解js——一切都是对象
  4. photoshop:找不到增效工具入口点
  5. 巧妙使用checkbox制作纯css动态导航栏
  6. 微信小程序图片放大预览
  7. (Matlab)GPU计算及CPU计算能力的比较
  8. mysql /tmp目录爆满问题的处理
  9. Jenkins的安装、启动和配置
  10. HTTP 代理服务器技术选型之旅
  11. MFC如何获取控件相对于窗口的左边,以及鼠标相对于控件的位置
  12. 如何将word中的图片和文字导入自己的博客中
  13. mac下面安装redis
  14. 寒武纪-1005 Travel(树形DP)
  15. Visual Studio 2017 离线安装
  16. Leetcode 1019. Next Greater Node In Linked List
  17. 将一个jar包放到linux下定时执行
  18. myEclipse如何将程序部署到tomcat(附录MyEclipse调试快捷键)
  19. jmeter解压后启动jmeter.bat报错:Not able to find java executable or version
  20. C51存储的优化

热门文章

  1. ASP.NET中页面加载时文本框(texbox控件)内有文字获得焦点时文字消失
  2. Javasript中Date日期常用用法(正则、比较)
  3. web服务器顺带网络负载均衡
  4. .NET 的webservice例子
  5. 第六十五篇、OC_iOS7 自定义转场动画push pop
  6. iOS开发--UIKit控件之UISearchBar(搜索栏)
  7. OC4_单例
  8. OC7_单词个数
  9. Tomcat上配置连接池{ connect error=Name [jdbc/OracleDB] is not bound in this Context. Unable to find [jdbc]}
  10. 创建ID3D11Device可能会遇到的问题,不能使用具体的IDXGIAdapter