A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 别想太多 中级黑马   /  2015-5-25 14:06  /  592 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

1.在同步方法中使用wait()、notify()方法

首先要理解notify()和wait(),按照Think in Java中的解释:"wait()允许我们将线程置入"睡眠"状态,同时又"积极"地等待条件发生改变.而且只有在一个notify()或 notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."

"wait()允许我们将线程置入"睡眠"状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的.

那和sleep,suspend有什么区别呢?

区别在于"(wait)同时又"积极"地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因为我们需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着, 等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放.而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁。在同步方法中使用wait()方法,使本线程等待,并允许其他线程使用这个同步方法。

其他线程使用完这个同步方法后,等待的线程怎么把对象锁收回来呢?

第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回.

第二种方法,让在使用的线程通知我,他用完了,要还给我了.调用notify()方法进行通知。

2.具体例子

生产者和消费者是从OS中的许多实际同步问题中抽象出来的具有代表性的问题。通过一个生产者--消费者的例子来说明synchronized和wait,notify之间的关系。

生产者生产,消费者消费。由于生产者和消费者彼此独立,且运行速度不确定。所以很可能出现生产者已进行生产,而消费者还没有得到信息的情况。为此,需要引入一组存储单元,组成缓冲区域,以便存放生产者所生产的信息。

如果要使生产者和消费者进程协调,必须定义如下规则:

1)只要缓存有存储单元,生产者可以进行生产,但当缓存已满,生产者必须等待

2)只要缓存不为空,消费者可以进行消费;但当缓存为空,消费者必须等待。

3)生产者和消费者不能同时读写缓存。

源码如下:

(1)消费者


  1. public class Consumer implements Runnable {
  2.     private Mointor m;
  3.     public Consumer(Mointor m) {
  4.       this.f = f;
  5.       new Thread(this, "Consumer").start();
  6.     }
  7.    
  8.     public void run() {
  9.         while(true) {
  10.             if(!f.suspend)
  11.             {
  12.               f.put();
  13.             }
  14.           }
  15.     }
  16. }
复制代码
(2)生产者类
  1. public class Producer implements Runnable{
  2.     private Mointor m;
  3.    public Producer(Mointor m) {
  4.       this.m = m;
  5.       new Thread(this, "Producer").start();
  6.     }
  7.     public void run() {
  8.       int i = 0;
  9.       while(true) {
  10.           if(!f.suspend)
  11.           {
  12.             f.put(i++);
  13.           }
  14.         }
  15.     }
  16. }
复制代码
(3)管理类
  1. public class Mointor{
  2.     int product_count = 0;
  3.     int product_item;
  4.     int front=0,rear=0;
  5.     final static int MAX_NUM = 10;
  6.     int[] buffer = new int[MAX_NUM];
  7.     public synchronized int get() {
  8.       if(product_count == 0)
  9.         try {
  10.           System.out.println("没有库存了,消费者等待……");
  11.           Thread.sleep(1000);
  12.           wait();
  13.        } catch(InterruptedException e) {
  14.           System.out.println("捕获中断异常");
  15.         }
  16.         product_item=buffer[front];
  17.         product_count--;
  18.         front=(front + 1)%MAX_NUM;
  19.         System.out.println("消费者获得了一个产品。 仓库剩余产品数量为:" + (product_count));
  20.         notify();
  21.         return product_item;
  22.     }

  23.     public synchronized void put(int value) {
  24.       if(product_count == MAX_NUM)
  25.         try {
  26.             System.out.println("仓库已满,生产者等待……");
  27.             Thread.sleep(1000);
  28.             wait();
  29.         } catch(InterruptedException e) {
  30.           System.out.println("捕获中断异常");
  31.         }
  32.         buffer[rear]=value;
  33.         rear=(rear + 1)%MAX_NUM;
  34.         product_count++
  35.         System.out.println("生产者制造了一个产品。 仓库剩余产品数量为:" + product_count);
  36.         notify();
  37.     }
  38.    
  39.     public static void main(String[] args){
  40.         Mointor m = new Mointor();
  41.         Producer p = new Producer(m);
  42.         p.safeResume();
  43.         Consumer c = new Consumer(m);
  44.     }
  45. }
复制代码


评分

参与人数 1黑马币 +20 收起 理由
明天更好 + 20 很给力!

查看全部评分

3 个回复

正序浏览
嗯。楼主好好学。加油进黑马。。。
回复 使用道具 举报
顶一下!
回复 使用道具 举报
先顶再看,多线程~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马