對此的標準解決方案是:使用A的「動態代理」(java.lang.reflect.Proxy
)。這可以節省您幾乎所有的樣板代碼。
本網站和Google包含足夠的使用示例Proxy
。
另外:我建議不要爲每個調用使用一個新的線程 - 如果被調用的方法很短,這是非常昂貴的。您可以使用Callable
接口代替Runnable
,而使用線程池Executor
。這也可以讓你在你的界面的返回值:-)
編輯
只是爲了好玩我編寫動態代理和執行的事情。
鑑於以下接口A
和樣品實施B
:使用反射來調用任何java.lang.reflect.Method
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
看起來像這樣:
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);
}
}
在其中創建這樣的ReflectiveMethodCallable
的部分並給予ExecutorService
的是InvocationHandler
的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
創造createProxyFor
新Proxy
時使用。所述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
中完成。
- 無需爲每種方法編寫任何代碼。
沒有枚舉,既不在您的描述中,也不在所提供的代碼中。我不明白你的問題。請嘗試給出最簡單的例子,並用吝嗇的名字,而不是A,B,C,D等 –