简体   繁体   English

找到优雅的方法来包装可运行方法并将其作为函数传递给 java

[英]Find elegant way to wrap runnable method and pass it as a function in java

Im with java 11, Let's say I have multiple runnable methods all them are same structure except the number of parameters as in example:我使用 java 11,假设我有多个可运行的方法,除了参数的数量之外,它们都是相同的结构,例如:

private Runnable deleteIndex(String targetIndex) {
        return () -> {
            try {
                iIndexerManagementService.deleteIndex(targetIndex);
            } catch (Exception e) {
                log.error("Cannot perform delete:", e);
            }
        };
    }
    
    
private Runnable deleteDataBySource(String targetIndex, String source) {
        return () -> {
            try {
                indexerDocumentService.deleteBySource(targetIndex, source);
            } catch (Exception e) {
                log.error("Cannot perform delete:", e);
            }
        };
    }
    
    
private Runnable createDeleteTaskByScanID(String targetIndex, String scandId, String source) {
        return () -> {
            try {
                indexerDocumentService.deleteByScanId(targetIndex, scandId, source);
            } catch (Exception e) {
                log.error("Cannot perform delete:", e);
            }
        };
} .... 
  and more ....

Later on I use it like here on each runnable method:稍后我在每个可运行的方法上都使用它:

    public void submitDeleteIndexTask(String targetIndex) {
       Optional.ofNullable(syncControlRepository.findByName(CATALOG_ENTITY_TYPE_KEYWORD))
                        .ifPresent(strategy -> {
                            Future<?> future =  uploadersExecutor.submit(deleteIndex(targetIndex));
                            if (featureFlagEnabled && config.isTestProfile()) {
                                try {
                                    future.get(1, TimeUnit.MINUTES);
                                } catch (Exception e) {
                                    log.error("Cannot wait on thread block:", e);
                                }
                            }
                    });
            } 
.... and more

I works perfect.我工作完美。

But I want to find nicer elegant way not to hold lots of runnable methods in class cause it might be more.但我想找到更好的优雅方法,不要在课堂上保存很多可运行的方法,因为它可能更多。 My purpose create 1 generic runnable wrapper to be able pass any kind of function so when I'll use it i will pass only the function itself and the parameters to invoke.我的目的是创建 1 个通用可运行包装器来传递任何类型的函数,所以当我使用它时,我只会传递函数本身和要调用的参数。

I thought about this way, bit i'm not sure it is correct我是这样想的,有点不确定是否正确

// generic runnable wrapper to pass any function

    public Runnable runAsync(Function foo, Object o) {
        return () -> {
            try {
                foo.apply(o);
            } catch (Exception e) {
                log.error("Cannot perform delete:", e);
            }
        };
    }

and then it should be 1 general method to be able receive function to fit the runnables methods:然后它应该是一种能够接收函数以适应可运行方法的通用方法:

public void runGeneralAsync(... HERE PASS FUNCTION ..??. ) {
        Optional.ofNullable(syncControlRepository.findByName(CATALOG_ENTITY_TYPE_KEYWORD))
                .ifPresent(strategy -> {
                    Future<?> future =  uploadersExecutor.submit(runAsync(....FUNCTOIN... ?? ));
                    if (featureFlagEnabled && config.isTestProfile()) {
                        try {
                            future.get(1, TimeUnit.MINUTES);
                        } catch (Exception e) {
                            log.error("Cannot wait on thread block:", e);
                        }
                    }
            });
    }

Please advice请指教

What you're asking for is tantamount to 'stringly typed' / dynamic, and is fundamentally unjavalike.您所要求的等同于“字符串类型”/动态,并且从根本上不像java。 You may think you want this;你可能认为你想要这个; you don't.你没有。 The entire java ecosystem will be fighting you every step of the way if you try.如果您尝试,整个 Java 生态系统将在每一步都与您抗争。

NB: Your runGeneralAsync is deplorably bad - you're really abusing Optional here.注意:你的runGeneralAsync非常糟糕 - 你真的在这里滥用 Optional 。 That code is a long-winded way of saying: Look up a thingie, if it does exist, do this, if it does not, silently do nothing.该代码是一种冗长的说法:查找一个东西,如果它确实存在,则执行此操作,如果不存在,则默默地什么也不做。 Aside from the long-windedness (there's nothing wrong with if !), "Do nothing" is a horrible fallback.除了长篇大论( if没有什么问题!),“什么都不做”是一个可怕的后备。 Horrible in the sense of: A single bug in the name or setup means nothing happens, so, you'll be chasing that bug for hours.从某种意义上说是可怕的:名称或设置中的单个错误意味着没有任何事情发生,因此,您将追逐该错误数小时。 An NPE takes 1 minute. NPE 需要 1 分钟。 If you ever write code where you can't fathom null occuring, just write it.如果您曾经编写过无法理解null发生的代码,那就写吧。 If null does happen you want that exception, so you know where to fix things.如果 null 确实发生了,你想要那个异常,所以你知道在哪里解决问题。

At any rate:好歹:

Instead, Runnable, itself, is the answer.相反,Runnable 本身就是答案。 Wrap lambdas in lambdas.将 lambdas 包裹在 lambdas 中。

You're thinking of something like:你正在考虑类似的事情:


// API:
public void runGeneralAsync(String methodName, Object... args) {
  // Lots of reflective shenanigans to find it.
  // Lots of issues with dealing with exceptions -
  // what if the method name does not exist? What if the wrong amount
  // of args were passed? Or the wrong type? Or there is an overload?

  // .. and then of course code to stick it all into an executor.submit
}

// usage:

runGeneralAsync("deleteIndexTask", "my-index");

but what you want to do is something like this:但你想做的是这样的:

public void runGeneralAsync(Runnable task) {
  uploadersExecutor.submit(runAsync(....));
}

// usage:

runGeneralAsync(() -> deleteIndex("my-index"));

Depending on needs, you may want to use Callable instead of Runnable here (you can return things, and throw things).根据需要,您可能希望在此处使用Callable而不是Runnable (您可以返回东西,也可以扔东西)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM