zoukankan      html  css  js  c++  java
  • Java多线程系列三——实现线程同步的方法

    两种实现线程同步的方法

    方法 特性
    synchronized 不需要显式地加解锁,易实现
    ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁

    下文用三种不同的方式实现生产者/消费者模型

    • synchronized结合wait/notify/notifyAll
    • ReentrantLock结合Condition
    • BlockingQueue(内部仍然采用ReentrantLock实现)
    import java.util.Stack;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @Description: 三种方法实现生产者/消费者
     */
    public class ThreadSynchronizeTest {
    
        public static void main(String[] args) {
            ProducerConsumer producerConsumer = new ProducerConsumerViaBlockingQueue();
            producerConsumer.test();
        }
    }
    
    abstract class ProducerConsumer {
        protected int capacity = 10;
        protected int element = 0;
    
        protected abstract void produce() throws InterruptedException;
    
        protected abstract void consume() throws InterruptedException;
    
        public void test() {
            Thread producer = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            produce();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            Thread consumer = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            consume();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            producer.start();
            consumer.start();
        }
    }
    
    /**
     * 方法一:ReentrantLock结合Condition
     */
    class ProducerConsumerViaReentrantLock extends ProducerConsumer {
        private Stack<Integer> stack = new Stack<>();
        private ReentrantLock lock = new ReentrantLock();
        private Condition notFull = lock.newCondition();
        private Condition notEmpty = lock.newCondition();
    
        @Override
        protected void produce() throws InterruptedException {
            try {
                lock.lock();
                if (stack.size() == capacity) {
                    notFull.await();
                }
                ++element;
                System.out.println(Thread.currentThread().getId() + " produce " + element);
                stack.push(element);
                notEmpty.signalAll();
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        protected void consume() throws InterruptedException {
            try {
                lock.lock();
                if (stack.isEmpty()) {
                    notEmpty.await();
                }
                int element = stack.pop();
                System.out.println(Thread.currentThread().getId() + " consume " + element);
                notFull.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }
    
    /**
     * 方法二:synchronized结合wait/notify/notifyAll
     */
    class ProducerConsumerViaObjectLock extends ProducerConsumer {
        private Stack<Integer> stack = new Stack<>();
        private Object lock = new Object();
    
        @Override
        protected void produce() throws InterruptedException {
            /**
             * 1. lock为监视器<br/>
             * 2. wait/notify/notifyAll方法必须在synchronized块内调用<br/>
             * 3. 调用wait/notify/notifyAll方法但不持有监视器的使用权将会抛出java.lang.
             * IllegalMonitorStateException<br/>
             */
            synchronized (lock) {
                if (stack.size() == capacity) {
                    lock.wait();
                }
                ++element;
                System.out.println(Thread.currentThread().getId() + " produce " + element);
                stack.push(element);
                lock.notifyAll();
            }
        }
    
        @Override
        protected void consume() throws InterruptedException {
            synchronized (lock) {
                if (stack.isEmpty()) {
                    lock.wait();
                }
                int element = stack.pop();
                System.out.println(Thread.currentThread().getId() + " consume " + element);
                lock.notifyAll();
            }
        }
    }
    
    /**
     * 方法三:BlockingQueue
     */
    class ProducerConsumerViaBlockingQueue extends ProducerConsumer {
        private BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(capacity);
    
        @Override
        protected void produce() throws InterruptedException {
            ++element;
            System.out.println(Thread.currentThread().getId() + " produce " + element);
            queue.put(element);
        }
    
        @Override
        protected void consume() throws InterruptedException {
            int element = queue.take();
            System.out.println(Thread.currentThread().getId() + " consume " + element);
        }
    }
  • 相关阅读:
    网页加速的14条优化法则 网站开发与优化
    .NET在后置代码中输入JS提示语句(背景不会变白)
    C语言变量声明内存分配
    SQL Server Hosting Toolkit
    An established connection was aborted by the software in your host machine
    C语言程序设计 2009春季考试时间和地点
    C语言程序设计 函数递归调用示例
    让.Net 程序脱离.net framework框架运行
    C语言程序设计 答疑安排(2009春季 110周) 有变动
    软件测试技术,软件项目管理 实验时间安排 2009春季
  • 原文地址:https://www.cnblogs.com/hiver/p/7122749.html
Copyright © 2011-2022 走看看