Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2351218
  • 博文数量: 321
  • 博客积分: 3440
  • 博客等级: 中校
  • 技术积分: 2992
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-24 09:08
个人简介

我就在这里

文章分类

全部博文(321)

文章存档

2015年(9)

2014年(84)

2013年(101)

2012年(25)

2011年(29)

2010年(21)

2009年(6)

2008年(23)

2007年(23)

分类: Java

2014-11-09 10:56:21

在JAVA中,一共有四种方法支持同步,其中三个是同步方法,一个是管道方法。
1.       方法wait()/notify()
2.       方法await()/signal()
3.       阻塞队列方法BlockingQueue
4.       管道方法PipedInputStream/PipedOutputStream
下面我们看各个方法的实现:

1.       方法wait()/notify()

wait()和notify()是根类Object的两个方法,也就意味着所有的JAVA类都会具有这个两个方法,为什么会被这样设计呢?我们可以认为所有的对象默认都具有一个锁,虽然我们看不到,也没有办法直接操作,但它是存在的。
wait()方法表示:当缓冲区已满或空时,生产者或消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让另一个线程开始执行;
notify()方法表示:当生产者或消费者对缓冲区放入或取出一个产品时,向另一个线程发出可执行通知,同时放弃锁,使自己处于等待状态。
下面是一个例子代码:

  1. package thread;
  2. import java.util.LinkedList;

  3. public class ProducerConsumer {
  4.     private LinkedList<Object> storeHouse = new LinkedList<Object>();
  5.     private int MAX = 10;

  6.     public ProducerConsumer() {
  7.     }

  8.     public void start() {
  9.         new Producer().start();
  10.         new Comsumer().start();
  11.     }

  12.     class Producer extends Thread {
  13.         public void run() {
  14.             while (true) {
  15.                 synchronized (storeHouse) {
  16.                     try {
  17.                         while (storeHouse.size() == MAX) {
  18.                             System.out.println("storeHouse is full , please wait");
  19.                             storeHouse.wait();
  20.                         }
  21.                         Object newOb = new Object();
  22.                         if (storeHouse.add(newOb)) {
  23.                             System.out.println("Producer put a Object to storeHouse");
  24.                             Thread.sleep((long) (Math.random() * 3000));
  25.                             storeHouse.notify();
  26.                         }
  27.                     } catch (InterruptedException ie) {
  28.                         System.out.println("producer is interrupted!");
  29.                     }

  30.                 }
  31.             }
  32.         }
  33.     }

  34.     class Comsumer extends Thread {
  35.         public void run() {
  36.             while (true) {
  37.                 synchronized (storeHouse) {
  38.                     try {
  39.                         while (storeHouse.size() == 0) {
  40.                             System.out.println("storeHouse is empty , please wait");
  41.                             storeHouse.wait();
  42.                         }
  43.                         storeHouse.removeLast();
  44.                         System.out.println("Comsumer get a Object from storeHouse");
  45.                         Thread.sleep((long) (Math.random() * 3000));
  46.                         storeHouse.notify();
  47.                     } catch (InterruptedException ie) {
  48.                         System.out.println("Consumer is interrupted");
  49.                     }

  50.                 }
  51.             }

  52.         }
  53.     }

  54.     public static void main(String[] args) throws Exception {
  55.         ProducerConsumer pc = new ProducerConsumer();
  56.         pc.start();
  57.     }
  58. }

2.       方法await()/signal()

在JDK5.0以后,JAVA提供了新的更加健壮的线程处理机制,包括了同步、锁定、线程池等等,它们可以实现更小粒度上的控制。await()和 signal()就是其中用来做同步的两种方法,它们的功能基本上和wait()/notify()相同,完全可以取代它们,但是它们和新引入的锁定机制 Lock直接挂钩,具有更大的灵活性。
下面是一个例子代码:

  1. package thread;

  2. import java.util.LinkedList;
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;

  6. public class ProducerConsumer2 {
  7.     private LinkedList<Object> myList = new LinkedList<Object>();
  8.     private int MAX = 10;
  9.     private final Lock lock = new ReentrantLock();
  10.     private final Condition full = lock.newCondition();
  11.     private final Condition empty = lock.newCondition();

  12.     public ProducerConsumer2() {
  13.     }

  14.     public void start() {
  15.         new Producer().start();
  16.         new Consumer().start();
  17.     }

  18.     public static void main(String[] args) throws Exception {
  19.         ProducerConsumer2 s2 = new ProducerConsumer2();
  20.         s2.start();
  21.     }

  22.     class Producer extends Thread {
  23.         public void run() {
  24.             while (true) {
  25.                 lock.lock();
  26.                 try {
  27.                     while (myList.size() == MAX) {
  28.                         System.out.println("warning: it's full!");
  29.                         full.await();
  30.                     }
  31.                     Object o = new Object();
  32.                     if (myList.add(o)) {
  33.                         System.out.println("Producer: " + o);
  34.                         empty.signal();
  35.                     }
  36.                 } catch (InterruptedException ie) {
  37.                     System.out.println("producer is interrupted!");
  38.                 } finally {
  39.                     lock.unlock();
  40.                 }
  41.             }
  42.         }
  43.     }

  44.     class Consumer extends Thread {
  45.         public void run() {
  46.             while (true) {
  47.                 lock.lock();
  48.                 try {
  49.                     while (myList.size() == 0) {
  50.                         System.out.println("warning: it's empty!");
  51.                         empty.await();
  52.                     }
  53.                     Object o = myList.removeLast();
  54.                     System.out.println("Consumer: " + o);
  55.                     full.signal();
  56.                 } catch (InterruptedException ie) {
  57.                     System.out.println("consumer is interrupted!");
  58.                 } finally {
  59.                     lock.unlock();
  60.                 }
  61.             }
  62.         }
  63.     }

  64. }

3.       阻塞队列方法BlockingQueue

BlockingQueue也是JDK5.0的一部分,它是一个已经在内部实现了同步的队列,实现方式采用的是我们的第2种await()/signal()方法。它可以在生成对象时指定容量大小。
它用于阻塞操作的是put()和take()方法。
put()方法类似于我们上面的生产者线程,容量最大时,自动阻塞。
take()方法类似于我们上面的消费者线程,容量为0时,自动阻塞。
下面是一个例子代码:

  1. package thread;

  2. import java.util.concurrent.*;

  3. public class ProducerConsumer3 {
  4.     // 建立一个阻塞队列
  5.     private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);

  6.     public ProducerConsumer3() {
  7.     }

  8.     public void start() {
  9.         new Producer().start();
  10.         new Consumer().start();
  11.     }

  12.     public static void main(String[] args) throws Exception {
  13.         ProducerConsumer3 s3 = new ProducerConsumer3();
  14.         s3.start();
  15.     }

  16.     class Producer extends Thread {
  17.         public void run() {
  18.             while (true) {
  19.                 try {
  20.                     Object o = new Object();
  21.                     // 取出一个对象
  22.                     queue.put(o);
  23.                     System.out.println("Producer: " + o);
  24.                 } catch (InterruptedException e) {
  25.                     System.out.println("producer is interrupted!");
  26.                 }
  27.             }
  28.         }
  29.     }

  30.     class Consumer extends Thread {
  31.         public void run() {
  32.             while (true) {
  33.                 try {
  34.                     // 取出一个对象
  35.                     Object o = queue.take();
  36.                     System.out.println("Consumer: " + o);
  37.                 } catch (InterruptedException e) {
  38.                     System.out.println("producer is interrupted!");
  39.                 }
  40.             }
  41.         }
  42.     }

  43. }

4.       管道方法PipedInputStream/PipedOutputStream

这个类位于java.io包中,是解决同步问题的最简单的办法,一个线程将数据写入管道,另一个线程从管道读取数据,这样便构成了一种生产者/消费者的缓冲区编程模式。

  1. package thread;

  2. import java.io.*;

  3. public class ProducerConsumer4{
  4.     private PipedOutputStream pos;
  5.     private PipedInputStream pis;
  6.     //private ObjectOutputStream oos;
  7.     //private ObjectInputStream ois;
  8.     
  9.     public ProducerConsumer4(){
  10.         try{
  11.             pos = new PipedOutputStream();
  12.             pis = new PipedInputStream(pos);
  13.             //oos = new ObjectOutputStream(pos);
  14.             //ois = new ObjectInputStream(pis);
  15.         }catch(IOException e){
  16.             System.out.println(e);
  17.         }
  18.     }
  19.     
  20.     public void start(){
  21.         new Producer().start();
  22.         new Consumer().start();
  23.     }
  24.     
  25.     public static void main(String[] args) throws Exception{
  26.         ProducerConsumer4 s4 = new ProducerConsumer4();
  27.         s4.start();
  28.     }
  29.     
  30.     class Producer extends Thread{
  31.         public void run(){
  32.             try{
  33.                 while(true){
  34.                     int b = (int) (Math.random() * 255);
  35.                     System.out.println("Producer: a byte, the value is " + b);
  36.                     pos.write(b);
  37.                     pos.flush();
  38.                     //Object o = new MyObject();
  39.                     //oos.writeObject(o);
  40.                     //oos.flush();
  41.                     //System.out.println("Producer: " + o);
  42.                 }
  43.             }catch(Exception e){
  44.                 //System.out.println(e);
  45.                 e.printStackTrace();
  46.             }finally{
  47.                 try{
  48.                     pos.close();
  49.                     pis.close();
  50.                     //oos.close();
  51.                     //ois.close();
  52.                 }catch(IOException e){
  53.                     System.out.println(e);
  54.                 }
  55.             }
  56.         }
  57.     }
  58.     
  59.     class Consumer extends Thread{
  60.         public void run(){
  61.             try{
  62.                 while(true){
  63.                     int b = pis.read();
  64.                     System.out.println("Consumer: a byte, the value is " + String.valueOf(b));
  65.                     //Object o = ois.readObject();
  66.                     //if(o != null)
  67.                         //System.out.println("Consumer: " + o);
  68.                 }
  69.             }catch(Exception e){
  70.                 //System.out.println(e);
  71.                 e.printStackTrace();
  72.             }finally{
  73.                 try{
  74.                     pos.close();
  75.                     pis.close();
  76.                     //oos.close();
  77.                     //ois.close();
  78.                 }catch(IOException e){
  79.                     System.out.println(e);
  80.                 }
  81.             }
  82.         }
  83.     }
  84.     
  85.     //class MyObject implements Serializable {
  86.     //}
  87. }
转自:http://blog.csdn.net/jiutianhe/article/details/32317733



阅读(1384) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~