zoukankan      html  css  js  c++  java
  • 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并发编程实战》 龙果学院

  • 相关阅读:
    httpclient 发送 json数据,微信security.msgSecCheck,
    win10 输入法,添加美式键盘,调整顺序
    activiti与spring的集成
    spring 中实例化Bean的三种方式
    工作流activiti的HelloWorld
    工作流Activiti的前置准备工作。
    Eclipse中配置约束(DTD,XSD)
    微信开发中,本地缓存,不同步的问题
    微信开发中碰到的坑,json传值,前台遍历json对象,跨页面转值,navigate层级限制
    用pageInfo对List手工分页
  • 原文地址:https://www.cnblogs.com/pony1223/p/9461013.html
Copyright © 2011-2022 走看看