【问题标题】:Java 7 Pass Method as Paramater for generic SQL Deadlock checkJava 7 传递方法作为通用 SQL 死锁检查的参数
【发布时间】:2017-08-12 14:16:59
【问题描述】:

在 Java 7 中是否可以将方法作为参数传递。

该方法将被调用并封装在一个 do while 中以检查 sql 死锁并重试。

我正在尝试一种通用的方法来处理表上存在锁时的死锁,因为目前有数千个插入和更新来复制这种情况。目前它只会查找 SQLException 但可以将其更改为 SQLException 的 getErrorCode 和目标 ER_LOCK_DEADLOCK。

下面的代码只是我想要实现的一个示例:

public void Object1Insert(Object1 object1){
    genericSQLRetry(insertObject1(object1));
}

public void Object2Insert(Object2 object2){
    genericSQLRetry(insertObject2(object2));
}

public void genericSQLRetry({method}){
    int retries = 5;
    boolean isException = false;
  do{
    try {
        isException = false;
        retries--;
        //Invoke method
        {method}
    }catch (SQLException e){
        isException = true;
    }

    if (isException & retries > 0){
        //getRandomSleep would be between 750-1250ms. This is to stop multiple retries at the same time.
        Thread.sleep(getRandomSleep());
    }
  }while (isException == true && retries > 0);
}

【问题讨论】:

    标签: java methods java-7 generic-programming database-deadlocks


    【解决方案1】:

    在 Java 7 中是否可以将方法作为参数传递。

    没有。这就是 Java 8 添加 lambda(包括方法引用)和函数式接口的原因。

    但是您可以在接口中定义方法,在调用类(可能是您在本地实例化的匿名类)中实现该接口,在genericSQLRetry 中接受该接口,然后在您收到的实例上调用该方法。

    在您的情况下,您可以重复使用 Runnable(这是他们在 Java 8 中为没有参数和没有返回值的 lambdas 所做的),并且:

    public void Object1Insert(final Object1 object1) {
        genericSQLRetry(new Runnable {
            public void run() {
                insertObject1(object1);
            }
        });
    }
    
    public void Object2Insert(Object2 object2) {
        genericSQLRetry(new Runnable {
            public void run() {
                insertObject2(object2);
            }
        });
    }
    
    public void genericSQLRetry(Runnable retryable) {
        int retries = 5;
        boolean isException = false;
        do {
            try {
                isException = false;
                retries--;
                //Invoke method
                retryable.run();
            }
            catch (SQLException e) {
                isException = true;
            }
    
            if (isException & retries > 0) {
                //getRandomSleep would be between 750-1250ms. This is to stop multiple retries at the same time.
                Thread.sleep(getRandomSleep());
            }
        } while (isException == true && retries > 0);
    }
    

    不过,就我个人而言,我更喜欢我自己的语义更清晰的界面:

    interface Retryable {
        void retry() {
        }
    }
    

    然后使用Retryable 而不是Runnable

    【讨论】:

      【解决方案2】:

      是的,如果你使用反射,你可以在某种程度上将方法作为参数传递。

      您将传递一个带有正确方法名称的字符串并使用

      Method method = this.getClass().getDeclaredMethod("methodName", new Class[]});
      

      然后使用:

      method.invoke(object)
      

      更多关于反射的信息可以在herehere找到,包括为什么你应该avoid using it

      【讨论】:

      • 是的,我知道反射,并且出于这些原因试图避免它。谢谢。
      • 欢迎您。您是否尝试过使用 JTA(Java 事务 API)来处理死锁?它可能会对你有所帮助。
      猜你喜欢
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多