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);
        }
    }
  • 相关阅读:
    numpy学习之矩阵之旅
    HDFS之深入简出(一)
    Hadoop特点
    ThreadLocal的理解
    DBCP连接数据库了解一下
    DBCP连接数据库了解一下
    axaj 的回调
    javaWEB登录ajax传值
    JavaWeb网站后台开发记录手册
    Python--控制循环语句
  • 原文地址:https://www.cnblogs.com/hiver/p/7122749.html
Copyright © 2011-2022 走看看