• Java并发编程原理与实战二十二:Condition的使用


    Condition的使用

    Condition用于实现条件锁,可以唤醒指定的阻塞线程。下面来实现一个多线程顺序打印a,b,c的例子。

    先来看用wait和notify的实现:

    public class Demo {

        private volatile int singal;

        public synchronized void a() {
            while (singal != 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("a");
            singal++;
            notifyAll();
        }

        public synchronized void b() {
            while (singal != 1) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("b");
            singal++;
            notifyAll();
        }

        public synchronized void c() {
            while (singal != 2) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("c");
            singal = 0;
            notifyAll();
        }

        public static void main(String[] args) {
            Demo demo = new Demo();
            A a = new A(demo);
            B b = new B(demo);
            C c = new C(demo);

            new Thread(a).start();
            new Thread(b).start();
            new Thread(c).start();
        }
    }

    class A implements Runnable {

        private Demo demo;

        public A(Demo demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.a();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class B implements Runnable {

        private Demo demo;

        public B(Demo demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.b();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class C implements Runnable {

        private Demo demo;

        public C(Demo demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.c();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    再来看一下用Condition的实现,可以发现Condition实现更方便,可以实现指定条件的唤醒:

    public class DemoCondition {

        private volatile int singal;

        private Lock lock = new ReentrantLock();

        private Condition a = lock.newCondition();

        private Condition b = lock.newCondition();

        private Condition c = lock.newCondition();

        public void a() {
            lock.lock();
            while (singal != 0) {
                try {
                    a.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("a");
            singal++;
            b.signal();
            lock.unlock();
        }

        public void b() {
            lock.lock();
            while (singal != 1) {
                try {
                    b.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("b");
            c.signal();
            singal++;
            lock.unlock();
        }

        public void c() {
            lock.lock();
            while (singal != 2) {
                try {
                    c.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("c");
            a.signal();
            singal = 0;
            lock.unlock();
        }

        public static void main(String[] args) {
            DemoCondition demo = new DemoCondition();
            A a = new A(demo);
            B b = new B(demo);
            C c = new C(demo);

            new Thread(a).start();
            new Thread(b).start();
            new Thread(c).start();
        }
    }

    class A implements Runnable {

        private DemoCondition demo;

        public A(DemoCondition demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.a();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class B implements Runnable {

        private DemoCondition demo;

        public B(DemoCondition demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.b();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class C implements Runnable {

        private DemoCondition demo;

        public C(DemoCondition demo) {
            this.demo = demo;
        }

        @Override
        public void run() {
            while (true) {
                demo.c();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    2.用Condition实现一个有界队列。

    public class MyQueue<E> {

        private Object[] obj;

        // 添加操作下标
        private int addIndex;

        // 删除操作下标
        private int removeIndex;

        // 实际队列长度
        private int queueSize;

        private Lock lock = new ReentrantLock();

        private Condition add = lock.newCondition();

        private Condition remove = lock.newCondition();

        public MyQueue(int count) {
            this.obj = new Object[count];
        }

        public void add(E e) {
            lock.lock();
            // 队列已满则等待
            while (queueSize == obj.length) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 队列已满,不能入队");
                    add.await();
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
            obj[addIndex++] = e;
            if (addIndex == obj.length - 1) {
                addIndex = 0;
            }
            queueSize++;
            System.out.println(Thread.currentThread().getName() + " 当前队列大小: " + queueSize);
            remove.signal();
            lock.unlock();
        }

        public void remove() {
            lock.lock();
            // 队列已空则等待
            while (queueSize == 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 队列已空,无法出队");
                    remove.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            obj[removeIndex] = null;
            if (++removeIndex == obj.length) {
                removeIndex = 0;
            }
            queueSize--;
            System.out.println(Thread.currentThread().getName() + " 当前队列长度: " + queueSize);
            add.signal();
            lock.unlock();
        }

        public static void main(String[] args) {
            final MyQueue<Integer> myQueue = new MyQueue<>(4);

            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        myQueue.add(1);
                    }
                }
            }.start();

            new Thread() {
                @Override
                public void run() {
                    myQueue.remove();
                }
            }.start();
        }
    }

    参考资料:

    《java并发编程实战》 龙果学院

  • 相关阅读:
    STL 源代码剖析 算法 stl_numeric.h -- copy
    SQLServer 复制和数据库镜像 具体配置部署
    2016第23周三
    2016第23周二
    2016第23周一
    2016第22周日
    2016第22周六
    2016第22周五
    五个JS经典面试题
    2016第22周三
  • 原文地址:https://www.cnblogs.com/pony1223/p/9461013.html
Copyright © 2020-2023  润新知