对此的标准解决方案是:java.lang.reflect.Proxy
为 A 使用“动态代理”( )。这可以节省您几乎所有的样板代码。
该站点和 Google 包含足够的Proxy
.
另外:我建议不要为每个调用使用一个新线程——如果调用的方法很短,这将非常昂贵。您可以改用Callable
接口Runnable
和线程池Executor
。这也允许您在界面中具有返回值:-)
编辑
只是为了好玩,我编写了动态代理和执行器的东西。
给定以下接口A
和示例实现B
:
interface A {
int a(int g, int f, int h);
int b(int x);
}
class B implements A {
@Override
public int a(int g, int f, int t) {
System.out.println("called a in thread "+Thread.currentThread().getName());
return 42;
}
@Override
public int b(int x) {
System.out.println("called b in thread "+Thread.currentThread().getName());
return 21;
}
}
正确Callable
使用反射调用 anyjava.lang.reflect.Method
如下所示:
class ReflectiveMethodCallable implements Callable<Object> {
private Object target;
private Method method;
private Object[] args;
public ReflectiveMethodCallable(Object target, Method method, Object[] args) {
this.target = target;
this.method = method;
this.args = args;
}
@Override
public Object call() throws Exception {
return method.invoke(target, args);
}
}
创建这样的 aReflectiveMethodCallable
并将其赋予 an 的ExecutorService
部分是InvocationHandler
of java.lang.reflect.Proxy
:
class MyInvocationHandler implements InvocationHandler {
private Object target;
private ExecutorService executorService;
public MyInvocationHandler(Object target, ExecutorService executorService) {
this.target = target;
this.executorService = executorService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Callable<Object> task = new ReflectiveMethodCallable(target, method, args);
Future<Object> future = executorService.submit(task);
return future.get();
}
catch(ExecutionException e1){
try {
throw e1.getCause();
} catch(InvocationTargetException e2){
throw e2.getCause();
}
}
}
}
InvocationHandler
在创建新的Proxy
时使用createProxyFor
。该类的其余部分Main
用于 SSCCE 示例:
public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
// get B somehow
A a = new B();
// get proxy for B
A proxy = createProxyFor(a, executorService);
// call proxy
System.out.println("current thread: "+Thread.currentThread().getName());
int resultA = proxy.a(1,2,3);
System.out.println("calling a returned "+resultA);
int resultB = proxy.b(1);
System.out.println("calling b returned "+resultB);
}
static A createProxyFor(A a, ExecutorService executorService){
InvocationHandler h = new MyInvocationHandler(a, executorService);
A proxy = (A)Proxy.newProxyInstance(A.class.getClassLoader(), new Class[]{A.class}, h);
return proxy;
}
}
输出:
current thread: main
called a in thread pool-1-thread-1
calling a returned 42
called b in thread pool-1-thread-1
calling b returned 21
完成:
- 每个方法
A
都将在另一个线程中调用。
- 线程由线程池重用。
- 附加逻辑(例如时间测量、超时控制)可以在
invoke
或 中完成call
。
- 无需为每种方法编写任何代码。