zoukankan      html  css  js  c++  java
  • java基础>线程 生产者消费者问题 小强斋

    生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,

    如果不加以协调可能会出现以下情况:

    存储空间已满,而生产者占用着它,消费者等着生产者让出空间从而去除产品,生产者等着消费者消费产品,从而向空间中添加产品。互相等待,从而发生死锁。

    存储空间为空,而消费者占用着它,生产者等着消费者让出空间从而添加产品,消费者等着生产者生产产品,从而从空间中去除产品。互相等待,从而发生死锁。

    JAVA解决线程模型的三种方式

    1、wait()和notify()

    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(),即线程锁的方式

    package sort;
    
    import java.util.LinkedList;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ProducerConsumer {
        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 ProducerConsumer() {
        }
    
        public void start() {
            new Producer().start();
            new Consumer().start();
        }
    
        public static void main(String[] args) throws Exception {
            ProducerConsumer s2 = new ProducerConsumer();
            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、阻塞队列的方式

    import java.util.concurrent.*;
    
    public class ProducerConsumer {
        // 建立一个阻塞队列
        private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);
    
        public ProducerConsumer() {
        }
    
        public void start() {
            new Producer().start();
            new Consumer().start();
        }
    
        public static void main(String[] args) throws Exception {
            ProducerConsumer s3 = new ProducerConsumer();
            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!");
                    }
                    // }
                }
            }
        }
    
    }

    三种方式原理一致,都是对独占空间加锁,阻塞和唤醒线程,第一种方式比较传统,第三种方式最简单,只需存储和取用,线程同步的操作交由LinkedBlockingQueue全权处理。

    wait()和notify()其他例子

    产品类

    //生产的产品
    public class Product {
    	private  int productId;
    
    	public Product(int productId) {
    		this.productId = productId;
    	}
    
    	public int getProductId() {
    		return productId;
    	}
    
    	public void setProductId(int productId) {
    		this.productId = productId;
    	}
    
    	@Override
    	public String toString() {
    		return "product_"+productId;
    	}
    }

    仓库类

    import java.util.ArrayList;
    import java.util.List;
    
    public class StoreHouse {
    	private static final Integer initialSize = 10;
    	private List<Product> list = null;
    
    	public StoreHouse() {
    
    		this.list = new ArrayList<Product>(initialSize);
    
    	}
    
    	public synchronized void put(Product product) {
    		if (list.size() == StoreHouse.initialSize) {
    			try {
    				System.out.println("仓库已满,等待消费者消费");
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    
    		list.add(product);
    		System.out.println("放入仓库" + product);
    		notifyAll();
    
    	}
    
    	public synchronized void get() {
    		if (list.size() == 0) {
    			try {
    				System.out.println("仓库为空,等待生产者生产");
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		Product product = list.get(list.size()-1);
    		System.out.println("从仓库取出" + product);
    		list.remove(list.size()-1);
    		notifyAll();
    	}
    
    }

    生产者

    public class Producer implements Runnable {
    
    	StoreHouse storeHouse = null;
    
    	public Producer(StoreHouse storeHouse) {
    		this.storeHouse = storeHouse;
    	}
    
    	@Override
    	public void run() {
    		int i = 0;
    		while (true) {
    
    			Product product = new Product(++i);
    			storeHouse.put(product);
    			 try { 
    	                Thread.sleep(1000); 
    	            } catch (InterruptedException e) { 
    	                return; 
    	            } 
    
    		}
    	}
    
    }

    消费者

    public class Consumer implements Runnable {
    
    	StoreHouse storeHouse = null;
    
    	public Consumer(StoreHouse storeHouse) {
    		this.storeHouse = storeHouse;
    	}
    
    	@Override
    	public void run() {
    		int i = 0;
    		while (true) {
    			storeHouse.get();
    			 try { 
    	                Thread.sleep(1500); 
    	            } catch (InterruptedException e) { 
    	                return; 
    	            } 
    		}
    	}
    
    }


    客户端测试

    public class Client {
    
    	public static void main(String[] args) {
    		StoreHouse storeHouse = new StoreHouse();
    
    		Runnable producer = new Producer(storeHouse);
    		Runnable consumer = new Consumer(storeHouse);
    		Thread produceThread = new Thread(producer);
    		Thread consumeThread = new Thread(consumer);
    		produceThread.start();
    		consumeThread.start();
    	}
    
    }



     

  • 相关阅读:
    如何用meavn构建mahout项目
    项目分析:对于7种图书推荐算法的组合评测
    项目实战:Mahout构建图书推荐系统
    Mahout推荐算法API详解
    9. Palindrome Number
    26. Remove Duplicates from Sorted Array
    575. Distribute Candies
    单链表的逆置
    回文串的判断
    回文判断(一个栈是不是回文)
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5429391.html
Copyright © 2011-2022 走看看