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 中打破我的接口 - 一个用于每个方法然后使用可调用的,更不用说我仍然需要找到一种方法将调用添加到阻塞队列(使用执行程序)
所以,我的疑惑是:
- 是否可以在已经 existing/implemented 的方法上包装可调用对象?
- 另一个想法是为每个需要实现可调用的方法创建一个抽象class,然后使用策略模式来决定使用哪个实现
例如:
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);
}
我正在尝试使用多种方法实现 java 可调用 而我的情况是这样的:
interface FsHandler {
boolean existDirectory();
boolean existFile(File);
...
}
interface FileHandler {
void write(byte[]);
void read(byte[]);
...
}
所有这些方法都是由不同的存储后端实现的,如本地文件系统、aws s3 等
在寻找并行化此代码的方法时,我尝试使用 callable,但如果我理解正确,我将需要在许多实现 callable 的小抽象 classes 中打破我的接口 - 一个用于每个方法然后使用可调用的,更不用说我仍然需要找到一种方法将调用添加到阻塞队列(使用执行程序)
所以,我的疑惑是:
- 是否可以在已经 existing/implemented 的方法上包装可调用对象?
- 另一个想法是为每个需要实现可调用的方法创建一个抽象class,然后使用策略模式来决定使用哪个实现
例如:
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
.
相反,您可以使用方法引用或 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);
}