thread的wait\notify实现线程通信

来源:互联网 发布:人力资源公司源码 编辑:程序博客网 时间:2024/05/21 06:15

背景:

之前的文章介绍过wait与sleep的区别,本文从另一个角度梳理一种实现线程通信的方式。

正文:

  wait()、notify()和notifyAll()是Object类中的方法:

  1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。

  2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)

  3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;

  4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程;

为何这三个不是Thread类声明中的方法,而是Object类中声明的方法(当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。

package thread;public class NotifyTest {    public static Object object = new Object();    public static void main(String[] args) {        Thread1 thread1 = new Thread1();        Thread2 thread2 = new Thread2();                 thread1.start();                 try {            Thread.sleep(200);        } catch (InterruptedException e) {            e.printStackTrace();        }                 thread2.start();    }         static class Thread1 extends Thread{        @Override        public void run() {            synchronized (object) {                try {                    object.wait();                } catch (InterruptedException e) {                }                System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");            }        }    }         static class Thread2 extends Thread{        @Override        public void run() {            synchronized (object) {                object.notify();                System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
<pre name="code" class="java"> <span style="white-space:pre"></span>System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");
} } }}
运行结果如下:


当然wait还有几个重载的方法设置超时时间:

public final void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException

导致线程进入等待状态直到它被通知或者经过指定的时间.

线面来看个常用的生产者消费者模式。模拟一个容器:

package thread;import java.util.LinkedList;public class Depository { int capability = 5;      private static LinkedList<Product> pool = new LinkedList();      public LinkedList getPool() {          return pool;      }      public synchronized int getSize() {          return pool.size();      }      public synchronized boolean isEmpty() {          return pool.isEmpty();      }      public synchronized boolean isFull() {         if (this.getSize() == this.capability) {              return true;          } else {              return false;          }      }    public synchronized void addLast(Product p) {          this.notifyAll();          if (!this.isFull()) {              pool.addFirst(p);              //System.out.println("当前线程的名称:" + Thread.currentThread().getName());              System.out.println(Thread.currentThread().getName() + " 放入一个产品");              System.out.println("仓库已经有 " + this.getSize() + " 个了");                       } else {              System.out.println("仓库满了,该线程" + Thread.currentThread().getName() + "等待");                        try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}                         }    }         public synchronized Product remove(){        if(!this.isEmpty()){//不为空,取出    this.notifyAll();  //    Product p=pool.removeFirst();        return p;    }else{//等待     System.out.println("仓库空了,该线程" + Thread.currentThread().getName() + "等待");       try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}            return null;    }    }}

package thread;public class Product {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public String toString(){return "product:"+this.name;}}

package thread;/** *  * @author zhangliang * * 2016年4月8日 下午1:57:32 */public class PCTest {public static void main(String[] args) throws InterruptedException {// TODO Auto-generated method stubPCTest test = new PCTest();Depository pool = new Depository(); Producer pro=test.new Producer(pool);        Consumer con=test.new Consumer(pool);      Thread p =  new Thread(pro);      Thread c1 =  new Thread(con);      Thread c2 =  new Thread(con);      p.start();      c1.start();      c2.start();        Thread.sleep(500);        p.interrupt();        c1.interrupt();        c2.interrupt();        }class Consumer implements Runnable{    //消费者线程拥有的资源    private Depository pool=null;    //构造函数    public Consumer(Depository pool)    {        this.pool=pool;    }    volatile boolean flag=true;    @Override    public void run() {       while(flag){            try {                Thread.sleep(100);            } catch (InterruptedException e) {                             flag =false;            }            Product p = this.pool.remove();            if(p!= null)            {            System.out.println("线程"+Thread.currentThread().getName()+"消费了"+p.toString());            }        }    }}//生产者线程class Producer implements Runnable{    //生产者线程拥有的资源    private Depository pool=null;    //构造函数    public Producer(Depository pool)    {        this.pool=pool;    }       @Override    public void run() {        boolean flag=false;        while(true)      {        if(!pool.isFull())        {            Product p  = new Product();            p.setName("p:"+System.currentTimeMillis());                this.pool.addLast(p);                try {Thread.sleep(10);} catch (InterruptedException e) {flag =false;}        }           }     }}}

运行结果如下:

Thread-0 放入一个产品仓库已经有 1 个了Thread-0 放入一个产品仓库已经有 2 个了Thread-0 放入一个产品仓库已经有 3 个了Thread-0 放入一个产品仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150363Thread-0 放入一个产品仓库已经有 4 个了线程Thread-1消费了product:p:1460095150373Thread-0 放入一个产品仓库已经有 5 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150443线程Thread-1消费了product:p:1460095150536Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150546Thread-0 放入一个产品线程Thread-1消费了product:p:1460095150433仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-1消费了product:p:1460095150646Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150739Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150749线程Thread-1消费了product:p:1460095150636Thread-0 放入一个产品仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了

1. 线程的等待或者唤醒,并不是让线程调用自己的wait或者notify方法,而是通过调用线程共享对象的wait或者notify方法来实现。
2. 线程要调用某个对象的wait或者notify方法,必须先取得该对象的监视器。
3. 线程的协作必须以线程的互斥为前提,这种协作实际上是一种互斥下的协作。

好了,本篇先到这里,下篇改用condition实现。




参考:

http://www.cnblogs.com/dolphin0520/p/3920385.html

0 0
原创粉丝点击