Java 生产者消费者问题
来源:互联网 发布:淘宝佣金是多少 编辑:程序博客网 时间:2024/05/01 15:07
在JAVA中,一共有四种方法支持同步,其中三个是同步方法,一个是管道方法。
1. 方法wait()/notify()
2. 方法await()/signal()
3. 阻塞队列方法BlockingQueue
4. 管道方法PipedInputStream/PipedOutputStream
下面我们看各个方法的实现:
1. 方法wait()/notify()
wait()和notify()是根类Object的两个方法,也就意味着所有的JAVA类都会具有这个两个方法,为什么会被这样设计呢?我们可以认为所有的对象默认都具有一个锁,虽然我们看不到,也没有办法直接操作,但它是存在的。
wait()方法表示:当缓冲区已满或空时,生产者或消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让另一个线程开始执行;
notify()方法表示:当生产者或消费者对缓冲区放入或取出一个产品时,向另一个线程发出可执行通知,同时放弃锁,使自己处于等待状态。
下面是一个例子代码:
package thread;import java.util.LinkedList;public class ProducerConsumer { private LinkedList<Object> storeHouse = new LinkedList<Object>(); private int MAX = 10; public ProducerConsumer() { } public void start() { new Producer().start(); new Comsumer().start(); } class Producer extends Thread { public void run() { while (true) { synchronized (storeHouse) { try { while (storeHouse.size() == MAX) { System.out.println("storeHouse is full , please wait"); storeHouse.wait(); } Object newOb = new Object(); if (storeHouse.add(newOb)) { System.out.println("Producer put a Object to storeHouse"); Thread.sleep((long) (Math.random() * 3000)); storeHouse.notify(); } } catch (InterruptedException ie) { System.out.println("producer is interrupted!"); } } } } } class Comsumer extends Thread { public void run() { while (true) { synchronized (storeHouse) { try { while (storeHouse.size() == 0) { System.out.println("storeHouse is empty , please wait"); storeHouse.wait(); } storeHouse.removeLast(); System.out.println("Comsumer get a Object from storeHouse"); Thread.sleep((long) (Math.random() * 3000)); storeHouse.notify(); } catch (InterruptedException ie) { System.out.println("Consumer is interrupted"); } } } } } public static void main(String[] args) throws Exception { ProducerConsumer pc = new ProducerConsumer(); pc.start(); }}
2. 方法await()/signal()
在JDK5.0以后,JAVA提供了新的更加健壮的线程处理机制,包括了同步、锁定、线程池等等,它们可以实现更小粒度上的控制。await()和signal()就是其中用来做同步的两种方法,它们的功能基本上和wait()/notify()相同,完全可以取代它们,但是它们和新引入的锁定机制Lock直接挂钩,具有更大的灵活性。
下面是一个例子代码:
package thread;import java.util.LinkedList;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ProducerConsumer2 { private LinkedList<Object> myList = new LinkedList<Object>(); private int MAX = 10; private final Lock lock = new ReentrantLock(); private final Condition full = lock.newCondition(); private final Condition empty = lock.newCondition(); public ProducerConsumer2() { } public void start() { new Producer().start(); new Consumer().start(); } public static void main(String[] args) throws Exception { ProducerConsumer2 s2 = new ProducerConsumer2(); s2.start(); } class Producer extends Thread { public void run() { while (true) { lock.lock(); try { while (myList.size() == MAX) { System.out.println("warning: it's full!"); full.await(); } Object o = new Object(); if (myList.add(o)) { System.out.println("Producer: " + o); empty.signal(); } } catch (InterruptedException ie) { System.out.println("producer is interrupted!"); } finally { lock.unlock(); } } } } class Consumer extends Thread { public void run() { while (true) { lock.lock(); try { while (myList.size() == 0) { System.out.println("warning: it's empty!"); empty.await(); } Object o = myList.removeLast(); System.out.println("Consumer: " + o); full.signal(); } catch (InterruptedException ie) { System.out.println("consumer is interrupted!"); } finally { lock.unlock(); } } } }}
3. 阻塞队列方法BlockingQueue
BlockingQueue也是JDK5.0的一部分,它是一个已经在内部实现了同步的队列,实现方式采用的是我们的第2种await()/signal()方法。它可以在生成对象时指定容量大小。
它用于阻塞操作的是put()和take()方法。
put()方法类似于我们上面的生产者线程,容量最大时,自动阻塞。
take()方法类似于我们上面的消费者线程,容量为0时,自动阻塞。
下面是一个例子代码:
package thread;import java.util.concurrent.*;public class ProducerConsumer3 { // 建立一个阻塞队列 private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10); public ProducerConsumer3() { } public void start() { new Producer().start(); new Consumer().start(); } public static void main(String[] args) throws Exception { ProducerConsumer3 s3 = new ProducerConsumer3(); s3.start(); } class Producer extends Thread { public void run() { while (true) { try { Object o = new Object(); // 取出一个对象 queue.put(o); System.out.println("Producer: " + o); } catch (InterruptedException e) { System.out.println("producer is interrupted!"); } } } } class Consumer extends Thread { public void run() { while (true) { try { // 取出一个对象 Object o = queue.take(); System.out.println("Consumer: " + o); } catch (InterruptedException e) { System.out.println("producer is interrupted!"); } } } }}
4. 管道方法PipedInputStream/PipedOutputStream
这个类位于java.io包中,是解决同步问题的最简单的办法,一个线程将数据写入管道,另一个线程从管道读取数据,这样便构成了一种生产者/消费者的缓冲区编程模式。
package thread;import java.io.*;public class ProducerConsumer4{ private PipedOutputStream pos; private PipedInputStream pis; //private ObjectOutputStream oos; //private ObjectInputStream ois; public ProducerConsumer4(){ try{ pos = new PipedOutputStream(); pis = new PipedInputStream(pos); //oos = new ObjectOutputStream(pos); //ois = new ObjectInputStream(pis); }catch(IOException e){ System.out.println(e); } } public void start(){ new Producer().start(); new Consumer().start(); } public static void main(String[] args) throws Exception{ ProducerConsumer4 s4 = new ProducerConsumer4(); s4.start(); } class Producer extends Thread{ public void run(){ try{ while(true){ int b = (int) (Math.random() * 255); System.out.println("Producer: a byte, the value is " + b); pos.write(b); pos.flush(); //Object o = new MyObject(); //oos.writeObject(o); //oos.flush(); //System.out.println("Producer: " + o); } }catch(Exception e){ //System.out.println(e); e.printStackTrace(); }finally{ try{ pos.close(); pis.close(); //oos.close(); //ois.close(); }catch(IOException e){ System.out.println(e); } } } } class Consumer extends Thread{ public void run(){ try{ while(true){ int b = pis.read(); System.out.println("Consumer: a byte, the value is " + String.valueOf(b)); //Object o = ois.readObject(); //if(o != null) //System.out.println("Consumer: " + o); } }catch(Exception e){ //System.out.println(e); e.printStackTrace(); }finally{ try{ pos.close(); pis.close(); //oos.close(); //ois.close(); }catch(IOException e){ System.out.println(e); } } } } //class MyObject implements Serializable { //}}
0 0
- java生产者 消费者问题
- Java生产者消费者问题
- java生产者消费者问题
- Java 生产者消费者问题
- java 生产者消费者问题
- Java生产者消费者问题 .
- [Java] 生产者&消费者问题
- Java 生产者消费者问题
- java 生产者消费者问题
- java 生产者消费者问题
- Java 生产者消费者问题
- java生产者消费者问题
- Java 生产者消费者问题
- java:生产者消费者问题
- Java-生产者消费者问题
- java-生产者消费者问题
- Java生产者消费者问题
- java消费者生产者问题
- Oracle SQL Developer 1.5.5设置关键字小写
- 二分查找法的实现和应用汇总
- 网站的基础:网站空间
- Java工程资源文件路径设置
- android字体大小根据分辨率自动调整
- Java 生产者消费者问题
- 转载:oracle: 浅谈sqlnet.ora文件的作用,及SQLNET.AUTHENTICATION_SERVICES设置
- Struts,JSP和XML解析三个问题
- valgrind-运行时诊断工具Memory Leak Check Tool
- •Web 服务器上的请求筛选被配置为拒绝该请求,因为查询字符串过长。
- 多线程GCD的使用
- 图算法三之BFS
- 我们都曾回不到的过去就这样慢慢地淡下来了