Java 7 将方法作为参数传递给通用 SQL 死锁检查

Java 7 Pass Method as Paramater for generic SQL Deadlock check

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

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

当 table 上有锁时,我正在尝试制定一种处理死锁的通用方法,因为目前有数千个插入和更新来复制它。目前它只会寻找 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);
}

In Java 7 is it possible pass the method as a paramater.

没有。这就是为什么 Java 8 添加了 lambda(包括方法引用)和功能接口。

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

在您的情况下,您可以重新使用 Runnable(这是他们在 Java 8 中对没有参数且没有 return 值的 lambda 所做的),并且:

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

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

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

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

然后使用:

method.invoke(object)

可以找到更多关于反射的信息here and here including why you should avoid using it