java 可通过多种方法调用

java callable with multiple methods

我正在尝试使用多种方法实现 java 可调用 而我的情况是这样的:

interface FsHandler {

  boolean existDirectory();
  boolean existFile(File);
  ...
}
interface FileHandler {

  void write(byte[]);
  void read(byte[]);
  ...
}

所有这些方法都是由不同的存储后端实现的,如本地文件系统、aws s3 等

在寻找并行化此代码的方法时,我尝试使用 callable,但如果我理解正确,我将需要在许多实现 callable 的小抽象 classes 中打破我的接口 - 一个用于每个方法然后使用可调用的,更不用说我仍然需要找到一种方法将调用添加到阻塞队列(使用执行程序)

所以,我的疑惑是:

例如:

interface WriteStrategy implements Callable<Void> {

  Void call();
  void write(byte[]);
  static WriteStrategy localFSStrategy(){...}
  static WriteStrategy S3Strategy() {...}

class FileHandler {
  private WriteStrategy strategy;

  public FileHandler(WriteStrategy strategy) {...}
  public void write(byte[]) { strategy.call(); }
}

我仍然不确定如何处理它:'(

我不确定你在找什么,但如果你想包装一个可调用的方法,你可以将它包装在一个匿名的 class 中,其中包括你想要的方法的对象包装,以及您要传递给它的任何参数。给定:

class A {
    int f1(final int i) {
        return i + i;
    }
}

看起来像这样:

Callable<Integer> callAF1 = new Callable<>() {
    private A callA = a;
    private int aParam1 = 1;

    @Override
    public Integer call() {
        return callA.f1(aParam1);
    }
};

那时你可以用callAF1做任何你想做的事。

您甚至不需要使用工具 Callable.

声明任何 classes

相反,您可以使用方法引用或 lambda 声明,它们具有 Callable 接口的正确签名以及 return 类型的适当自动装箱。这允许一个 class 提供多个 Callable 实现。

以下是一些不同样式的示例:

class Impl {
    public Impl() {};

    public void write(byte[] bytes) {
        throw new RuntimeException("not implemented yet");
    }
    public int doSomeOp() {
        return 0;
    }
    public byte[] read() {
        throw new RuntimeException("not implemented yet");
    }
}
public static void main(String[] args)
{
    Impl impl = new Impl();

    byte[] ba = {65, 66, 67};

    // Method references with different return types
    Callable<Integer> callable1 = impl::doSomeOp;
    Callable<byte[]>  callable2 = impl::read;

    // lambda for void method, or methods needing extra arguments
    Callable<Void>    callable3 = () -> { impl.write(ba); return null; };

    // Then you can use with ExecutorService:
    ExecutorService  executor = Executors.newCachedThreadPool();
    Future<Integer> task1 = executor.submit(callable1);
    
    // You don't even need to declare the local variable "callable1"
    Future<Integer> task2 = executor.submit(impl::doSomeOp);
}