我正在编写系列课程,所有这些都使用了相机。 每个班级有4种基本方法来初始化,启动,停止或释放相机。
我想在后台线程中运行这些方法。但我很难找到一个简单的方法来做到这一点。
我发现的唯一方法是使用定义为
的公共ExecutorService
ExecutorService backgroundThread = Executors.newSingleThreadExecutor();
然后,我必须将每个方法的代码包装这样的事情:
public void start(){
AbstractLight.backgroundThread.execute(new Runnable(){
public void run(){
//write "start method" code here
}
});
}
我想有一种更聪明的方法可以做到,但我不知道。有人这样做的伎俩吗?
谢谢
答案 0 :(得分:3)
您可以创建一个包含这些方法的“异步”版本的抽象父类。
从一个抽象的父类开始,然后将它们中的每一个包装在它们自己的runnable异步版本中。现在,无论何时从抽象父级继承,每个都将自动拥有自己的runnable。然后,您可以将它们放入执行者或父母所需的任何内容中。
public abstract class CameraParent
{
public abstract void init();
public abstract void start();
public abstract void stop();
public abstract void release();
public virtual Runnable initAsync()
{
Runnable r = new Runnable()
{
@Override
public void Run()
{
init();
}
}
return r;
}
public virtual Runnable startAsync()
{
Runnable r = new Runnable()
{
@Override
public void Run()
{
start();
}
}
return r;
}
public virtual Runnable stopAsync()
{
Runnable r = new Runnable()
{
@Override
public void Run()
{
stop();
}
}
return r;
}
public virtual Runnable releaseAsync()
{
Runnable r = new Runnable()
{
@Override
public void Run()
{
release();
}
}
return r;
}
}
这将为您正在编写的整个课程系列提供良好的基础,而无需在任何地方放置Runnables。
如果您想强制所有这些在后台线程上运行,请使抽象方法受到保护。然后将您的执行程序服务放在父类中,而不是返回Runnable,在执行程序服务中启动它。
您的每个子类现在都自动执行所有异步操作,但您只需实现这四种方法即可实现。
答案 1 :(得分:2)
您可以使用Queue
方法调用以及Router
来确定要调用的类的方法:
public interface Camera {
public void init();
public void start();
public void stop();
public void release();
}
public class Router implements Runnable {
private final EnumMap<CameraType, Camera> cameras = new EnumMap<>(CameraType.class);
private final BlockingQueue<RouterInvocation> queue = new LinkedBlockingQueue<>();
public enum CameraType {
CAMERA1, CAMERA2, //etc
}
private enum CameraMethod {
INIT, START, STOP, RELEASE
}
private class RouterInvocation {
public final Camera camera;
public final CameraMethod cameraMethod;
public RouterInvocation(Camera c, CameraMethod cm) {
this.camera = c;
this.cameraMethod = cm;
}
}
// similar methods for start, stop, release
public void init(CameraType cameraType) {
queue.offer(new RouterInvocation(cameras.get(cameraType), INIT);
}
public void run() {
try {
while(true) {
// wait for next RouterInvocation
RouterInvocation i = queue.take();
if(i.cameraType == INIT) {
i.camera.init();
} else if // same for remaining methods
}
} catch(InterruptedException ex) {
return;
}
}
}
好处是您只需要向Runnable
提交一个Router
(ExecutorService
) - Router
然后负责从中调用适当的方法适当的Camera
实施。
如果您决定要多个线程处理队列,那么您可以在多个Routers
之间共享队列,或者我的建议是将ExecutorService
移到Router
内(所以Router
不再实现Runnable
,而是创建内部Runnables
来处理队列。)