我使用的是 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 ....
后来我在每个可运行方法上都像这里一样使用它:
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
我工作完美。
但是我想找到更好的优雅的方法来不在类中保存大量可运行的方法,因为它可能会更多。 我的目的是创建 1 个通用的可运行包装器,以便能够传递任何类型的函数,因此当我使用它时,我将仅传递函数本身和要调用的参数。
我是这么想的,但我不确定它是否正确
// 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);
}
};
}
然后它应该是一种能够接收函数以适应可运行方法的通用方法:
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);
}
}
});
}
请指教
您所要求的等同于“字符串类型”/动态,并且从根本上来说与Java不同。你可能认为你想要这个;你不知道。如果你尝试的话,整个 Java 生态系统将在每一步中与你作斗争。
注意:你的
runGeneralAsync
非常糟糕 - 你真的在这里滥用 Optional
。该代码是一种冗长的说法:查找一个事物,如果它确实存在,则执行此操作,如果不存在,则默默地不执行任何操作。除了啰嗦(if
没有任何问题!)之外,“什么都不做”是一个可怕的后备方案。可怕的含义是:名称或设置中的一个错误意味着什么也不会发生,因此,您将花费几个小时来追踪该错误。 NPE 需要 1 分钟。如果您编写的代码无法理解 null
的发生,那就写它吧。如果 null 确实发生,您想要该异常,这样您就知道在哪里修复问题。
无论如何:
Runnable
本身就是答案。将 lambda 包裹在 lambda 中。
你正在想这样的事情:
// 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");
但是你想做的是这样的:
public void runGeneralAsync(Runnable task) {
uploadersExecutor.submit(runAsync(....));
}
// usage:
runGeneralAsync(() -> deleteIndex("my-index"));
Callable
代替这里的Runnable
(你可以归还东西,也可以扔东西)。