众妙之门

业精于勤,荒于嬉;行成于思,毁于随

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

关键字synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待/通知模式。
类ReentrantLock同样可以实现该功能,但是要借助于Condition对象。它具有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Condition(对象监视器)实例,线程对象可以注册在指定Condition中,从而有选择性的进行线程通知,在调度线程上更加灵活
使用notify和notifyAll方法进行通知时,被通知的线程是由JVM随机选择的,但是ReentrantLock结合Condition可以实现前面介绍过的“选择性通知”,这个功能是非常重要的。
synchronized相当于整个Lock对象中只有单一的Condition对象,所有线程都注册在它一个对象上,线程开始notifyAll()时,需要通知所有waiting的线程,没有选择权,会出现相当大的效率问题

简单例子:

public class TestLock implements Runnable {
    public static ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            for (int i = 0; i < 5; i++) {
                System.out.println(i);
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        TestLock lock = new TestLock();
        new Thread(lock).start();
        new Thread(lock).start();
        new Thread(lock).start();
    }
}

得到结果是顺序打印。

condition调用await()方法后,会释放lock,接收到同一个condition的signal后线程需要重新获得锁,

使用Condition例子:

public class TestLock {
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition newCondition = lock.newCondition();

    public static void main(String[] args) {
        class MyRunnable1 implements Runnable {
            @Override
            public void run() {
                try {
                    lock.lock();
                    System.out.println("myRunnable1:await:begin");
                    newCondition.await();
                    System.out.println("myRunnable1:await:end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
        ;

        class MyRunnable2 implements Runnable {
            @Override
            public void run() {
                try {
                    lock.lock();
                    System.out.println("myRunnable2:signal:begin");
                    newCondition.signal();
                    System.out.println("myRunnable2:signal:end");
                } finally {
                    lock.unlock();
                }
            }
        }

        new Thread(new MyRunnable1()).start();
        new Thread(new MyRunnable2()).start();
    }
}

结果:

 

posted on 2018-12-12 17:09  xuanm  阅读(331)  评论(0编辑  收藏  举报