如何在定义的线程(池)上运行类的方法?

时间:2015-06-22 14:04:02

标签: java android multithreading threadpool

我正在编写系列课程,所有这些都使用了相机。 每个班级有4种基本方法来初始化,启动,停止或释放相机。

我想在后台线程中运行这些方法。但我很难找到一个简单的方法来做到这一点。

我发现的唯一方法是使用定义为

的公共ExecutorService
ExecutorService backgroundThread = Executors.newSingleThreadExecutor();

然后,我必须将每个方法的代码包装这样的事情:

public void start(){
    AbstractLight.backgroundThread.execute(new Runnable(){
        public void run(){
            //write "start method" code here
        }
    });
}

我想有一种更聪明的方法可以做到,但我不知道。有人这样做的伎俩吗?

谢谢

2 个答案:

答案 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提交一个RouterExecutorService) - Router然后负责从中调用适当的方法适当的Camera实施。

如果您决定要多个线程处理队列,那么您可以在多个Routers之间共享队列,或者我的建议是将ExecutorService移到Router内(所以Router不再实现Runnable,而是创建内部Runnables来处理队列。)