Lock锁机制和synchronize分别实现生产者消费者例程

来源:互联网 发布:咫尺网络 微页 编辑:程序博客网 时间:2024/05/29 18:09

存在问题

像前面实现消费者生产者例程那样,地址,直接操作线程这种方式是可以的,但对于并发编程,这样的代码很快变得容易出错,特别是好几个线程需要协作来完成一个更大的任务的时候。这种情况下,它们的控制流需要被协调。

例如,一个线程的执行完成可能依赖于其他将要执行完成的线程。通常熟悉的例子就是生产者/消费者的例子,因为如果消费者队列是空的,那么生产者应该等待消费者,并且如果生产者队列是空的,那么消费者也应该等待生产者。该需求可能通过共享状态条件队列来实现,但是你仍然必须通过使用共享对象上的java.lang.Object.nofity()java.lang.Object.wait()来实现同步,这很容易出错。

最终,一个常见的错误就是在大段代码甚至整个方法上使用synchronize进行互斥。虽然这种方法能实现线程安全的代码,但是通常由于排斥时间太长而限制了并行性,从而造成性能低下。

用synchronize实现消费者生产者

package com.producerconsumer;import java.util.LinkedList;import java.util.Queue;import java.util.Random;public class ProducerConsumerInJava {    public static void main(String args[]) {        System.out.println("How to use wait and notify method in Java");        System.out.println("Solving Producer Consumper Problem");        Queue<Integer> buffer = new LinkedList<>();        int maxSize = 10;        Thread producer = new Producer(buffer, maxSize, "PRODUCER");        Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");        producer.start();        consumer.start();    }}/** * Producer Thread will keep producing values for Consumer to consumer. It will * use wait() method when Queue is full and use notify() method to send * notification to Consumer Thread. *  */class Producer extends Thread {    private Queue<Integer> queue;    private int maxSize;    public Producer(Queue<Integer> queue, int maxSize, String name) {        super(name);        this.queue = queue;        this.maxSize = maxSize;    }    @Override    public void run() {        while (true) {            synchronized (queue) {                while (queue.size() == maxSize) {                    try {                        System.out.println("Queue is full, " + "Producer thread waiting for "                                + "consumer to take something from queue");                        queue.wait();                    } catch (Exception ex) {                        ex.printStackTrace();                    }                }                Random random = new Random();                int i = random.nextInt();                System.out.println("Producing value : " + i);                queue.add(i);                queue.notifyAll();            }        }    }}/** * Consumer Thread will consumer values form shared queue. It will also use * wait() method to wait if queue is empty. It will also use notify method to * send notification to producer thread after consuming values from queue. *  */class Consumer extends Thread {    private Queue<Integer> queue;    private int maxSize;    public Consumer(Queue<Integer> queue, int maxSize, String name) {        super(name);        this.queue = queue;        this.maxSize = maxSize;    }    @Override    public void run() {        while (true) {            synchronized (queue) {                while (queue.isEmpty()) {                    System.out.println("Queue is empty," + "Consumer thread is waiting"                            + " for producer thread to put something in queue");                    try {                        queue.wait();                    } catch (Exception ex) {                        ex.printStackTrace();                    }                }                System.out.println("Consuming value : " + queue.remove());                queue.notifyAll();            }        }    }}

用ReentrantLock实现消费者生产者

package com.toc;import java.util.LinkedList;import java.util.Queue;import java.util.Random;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class TestReentrantLock {    public static void main(String[] args) throws InterruptedException {        System.out.println("How to use await and signal method in Java");        System.out.println("Solving Producer Consumper Problem");        // 锁对象        final Lock lock = new ReentrantLock();        Condition full = lock.newCondition();        Condition empty = lock.newCondition();        Queue<Integer> buffer = new LinkedList<>();        int maxSize = 10;        Thread producer = new Producer(lock, full, empty, buffer, maxSize, "PRODUCER");        Thread consumer = new Consumer(lock, full, empty, buffer, maxSize, "CONSUMER");        producer.start();        consumer.start();    }}class Producer extends Thread {    // 锁对象    private final Lock lock;    // 控制队列满的条件变量    private final Condition full;    // 控制队列空的条件变量    private final Condition empty;    private Queue<Integer> queue;    private int maxSize;    public Producer(Lock lock,Condition full,Condition empty, Queue<Integer> queue, int maxSize, String name) {        super(name);        this.queue = queue;        this.maxSize = maxSize;        this.lock = lock;        this.full = full;        this.empty = empty;    }    @Override    public void run() {        while(true){            // 获得锁              lock.lock();            try {                while (queue.size() == maxSize) {                    System.out.println("队列满了,等待消费者取走");                    // 由于条件不满足,生产阻塞                     full.await();                }                Random random = new Random();                int i = random.nextInt();                System.out.println("Producing value : " + i);                queue.add(i);                empty.signal();            } catch (InterruptedException e) {                e.printStackTrace();            } finally {                lock.unlock();            }        }    }}class Consumer extends Thread {    // 锁对象    private final Lock lock;    // 控制队列满的条件变量    private final Condition full;    // 控制队列空的条件变量    private final Condition empty;    private Queue<Integer> queue;    private int maxSize;    public Consumer(Lock lock,Condition full,Condition empty, Queue<Integer> queue, int maxSize, String name) {        super(name);        this.queue = queue;        this.maxSize = maxSize;        this.lock = lock;        this.full = full;        this.empty = empty;    }    @Override    public void run() {        // 获得锁          while (true) {            lock.lock();            try{                while (queue.isEmpty()) {                    System.out.println("队列空了,等待生产者生产");                    empty.await();                }                System.out.println("Consuming value : " + queue.remove());                full.signal();            }catch(InterruptedException e){                e.printStackTrace();            }finally{                lock.unlock();            }        }    }}
阅读全文
1 0