rom*_*rom 2 java concurrency enums word-wrap
我在java中有以下情况:我有一个名为"A"的接口,需要由程序启动后动态加载的类实现.让我们称它为B.这个接口提供x(多于1个)方法.让我们从()到z()调用em.现在我必须将这个类包装一段时间来测量和控制问题并在它自己的线程中运行它以便能够在需要太长时间时将其杀死.因此我发明了包含B的C类,因为B本身并没有实现runnable.下一部分是原始程序应该调用的类.新的D类D也实现了接口A以隐藏模型中的整个控制部分.现在我必须在D中包装接口的方法并将它们发送到C并将其解包给C,后者将它们解包并在对象B上执行它们.我希望我能够很好地解释它.
这里有一些我想象的示例代码可以是:
public class D implements A {
private C ai;
public D(String aiName) {
ai = new C("trivialKi");
}
private void call(parameters, ORIGIN_METHOD origin) {
AiTaskExecutor task = new AiTaskExecutor(parameters, origin, ai);
FutureTask<Long> tsk = new FutureTask<Long>(task);
Thread thread = new Thread(tsk);
thread.start();
if (abort) {
tsk.cancel(true);
}
}
@Override
public void a(g g, f f, t t) {
call(g, f, t, ORIGIN_METHOD.a);
}
@Override
public void b(g g, t t, h h) {
call(g, t, h, ORIGIN_METHOD.b);
}
@Override
public void c(g g, t t, f f) {
call(g, t, f, ORIGIN_METHOD.c);
}
}
Run Code Online (Sandbox Code Playgroud)
并且在C类中有明显的切换案例,该枚举用于将参数传递给类C中的正确方法,该类保存在类C als private字段中.
你有更好的解决方案吗?我个人不喜欢枚举的东西,如果参数太不同,这不会很好.这样的事情有"标准"解决方案吗?
The standard solution for this is: Use a "Dynamic Proxy" (java.lang.reflect.Proxy) for A. This saves you almost all your boilerplate code.
This site and Google contains enough usage examples for 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;
}
}
Run Code Online (Sandbox Code Playgroud)
正确Callable使用反射调用任何java.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);
}
}
Run Code Online (Sandbox Code Playgroud)
其中这样的部分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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
将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;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
完成:
A将在另一个线程中调用每个方法.invoke或内部完成call.