• Functional Programming in Java venkat(13) Working with Resources


    Functional Programming in Java venkat(13): Working with Resources

    这里是记录学习这本书 Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions 的读书笔记,如有侵权,请联系删除。

    Managing Locks

    并发编程中锁很重要。

    synchronize的弊端

    首先,对synchronized的调用很难超时,这会增加死锁和活锁的机会。

    其次,很难模拟出synchronized,这使得单元测试很难看到代码是否遵守了适当的线程安全性。

    First, it’s
    hard to time out a call to synchronized, and this can increase the chance of
    deadlocks and livelocks. Second, it’s hard to mock out synchronized, and that
    makes it really hard to unit-test to see if code adheres to proper thread safety

    为了解决这些问题,在Java 5中引入了Lock接口,以及一些实现,如ReentrantLock。Lock接口给了我们更好的锁定、解锁控制权,检查是否有锁,如果在一定的时间范围内没有获得锁,还可以轻松地超时展示出来。因为这是一个接口,很容易模拟它的实现用于单元测试。

    To address these concerns, the Lock interface, along with a few implementations such as ReentrantLock, was introduced in Java 5. The Lock interface gives us better control to lock, unlock, check if a lock is available, and easily time out if a lock is not gained within a certain time span. Because this is an interface, it’s easy to mock up its implementation for the sake of unit testing

    Lock的弊端,需要显式的unlock

    There’s one caveat to the Lock interface—unlike its counterpart synchronized, it
    requires explicit locking and unlocking. This means we have to remember to
    unlock, and to do the same in the finally block. From our discussions so far
    in this chapter, we can see lambda expressions and the execute around method
    pattern helping out quite a bit here.

    看一个显式使用lock的例子,需要在finally块中unlock

    public class Locking {
      Lock lock = new ReentrantLock(); //or mock
      
      protected void setLock(final Lock mock) {
        lock = mock;
      } 
    
      public void doOp1() {
        lock.lock();
        try {
          //...critical code...
        } finally {
          lock.unlock();
        }
      }
      //...
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    使用lambda表达式来简化lock的调用,我们把复杂的部分放在一个方法runLocked中,使得调用的方法接口更简洁。

    package fpij;
    
    import java.util.concurrent.locks.Lock;
    
    public class Locker {
      public static void runLocked(Lock lock, Runnable block) {
        lock.lock();
    	
        try {
          block.run();
        } finally {
          lock.unlock();
        }    
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    lambda表达式调用runLock方法

    
      public void doOp2() {
        runLocked(lock, () -> {/*...critical code ... */});
      }
      
      public void doOp3() {
        runLocked(lock, () -> {/*...critical code ... */});
      }
      
      public void doOp4() {
        runLocked(lock, () -> {/*...critical code ... */});
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    docker 镜像重启报错问题处理
    前端模块化导入导出
    GitLab CI/CD使用经验,来自于莫纳什大学的考试任务解析
    Uniapp扫码预览连接地址与手机不在同一网段
    微信小程序 vantweapp里面的上传upload组件研究
    JAVA基础(JAVA SE)学习笔记(六)面向对象编程(基础)
    《鸿蒙生态应用开发白皮书》读后感
    异或运算和相关例子
    Java之juc旅途-Executor(四)
    [杂记]C++中移动语义与完美转发的一些理解
  • 原文地址:https://blog.csdn.net/shizheng_Li/article/details/128104832