0

我有一个基于 Java 的应用程序 (Android),我希望能够在后台执行潜在的长时间操作。AsyncTask 上的 Android 文档建议不要将它们用于可能运行超过几秒钟的任务(为什么会这样?)所以我改用 Java 线程的子类。这个 Thread 子类(HPHeadThread)的目标主要是承载一些异步控制机制的实例,并为这些机制提供访问器方法供其他线程使用。我的目标是能够从引用 HPCHeadThread 的任何线程调用 hHPHeadThread.doStuff(),并让在 HPCHeadThread 中实例化的控制对象在 HPCHeadThread 线程上工作,并且仅在该线程上工作。当没有被其他线程访问时,HPCHeadThread 应该休眠,以免浪费 CPU 周期。

测试活动.java

//..snip
private HPCHeadThread hHPCHeadThread;

@Override
protected void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  //...snip 

  //Create and start our HPCHeadThread
  hHPCHeadThread = HPCHeadThread.getHPCThreadHead();
  hHPCHeadThread.start();

  //..snip
}

HPCHeadThread.java

//..snip
public class HPCHeadThread extends Thread {
  private static volatile HPCHeadThread instance;
  private static boolean bIsActive = true;


  private HPCHeadThread(){
    super();        
  }

  public static HPCHeadThread getHPCThreadHead(){

    if(instance == null && bIsActive){
      instance = new HPCHeadThread();   
    }

    return instance;

  }


  public void safeStop(){
    instance = null;
    bIsActive = false;
  }

  @Override
  public void run(){
  Thread thisThread = Thread.currentThread();
  Thread.currentThread().setName("HPC_Head_Thread");

  while(instance == thisThread){
    //Our HPCHeadThread 'main' loop
    //Try to have it sleep whenever it isn't being used
    //Hopefully it will wake nicely upon attempted access,
    //perform the desired function, and then return to sleep


      try{
        Thread.sleep(10000);
      }
      catch (InterruptedException e){
        //e.printStackTrace();
      }

    }//End while
  }//End Run()

  public void doStuff(){
    //..snip stuff..
  }

}

现在,如果我从我的主 TestActivity 线程中调用 hHPHeadThread.doStuff(),工作进程是在 HPCHeadThread 上还是在主 TestActivity 线程上?TestActivity 是否等待 doStuff() 方法返回,然后在其自己的线程中继续顺序执行?方法调用是否会唤醒 HPCHeadThread 和/或它们是否会导致在 HPCHeadThread 的 run() 方法的 while 循环中引发 InterruptedException?

4

2 回答 2

2

Android 文档建议不要在活动中长时间运行线程,因为活动可以在系统需要内存并且应用程序在后台运行的任何时候被换出。

如果您想做长时间运行的任务:创建一个专门用于此的服务:长时间运行的任务在需要更多内存时不应被丢弃。

关于排队的事情:听起来是个好建议。只需使用具有阻塞调用的 ArrayBlockingQueue:take()

像这样创建您的工作线程和队列:

public class Workqueue implements Runnable {


private static Workqueue theInstance=null;

public static synchronized Workqueue getInstance(){
   if(theInstance==null){
       theInstance=new WorkQueue();
     }
  return theInstance;
  }


private ArrayBlockingQueue<Runnable> queue=new ArrayBlockingQueue<Runnable>();
private Thread workerThread;

private WorkQueue(){
    workerThread=new Thread(this);
    workerThread.start();
}


public void run(){
   while(keepRunning){
      //pick up next task or wait (not using any cpu cycles)
      Runnable r=queue.take();
      //execute task
      r.run();
    }
}

public void addTask(Runnable task){
   queue.add(task);
}

用法是:

Runnable newTask= new Runnable(){
public void run(){
   dostuff...
}};
Workqueue.getInstance().addTask(newTask);

这可以从任何线程调用而不阻塞它,它将任务添加到队列中,这些任务将被一一执行。

于 2013-03-29T20:11:14.093 回答
0

首先,我认为您可以使用旧的 Singleton 设计模式来实现从任何地方都可以访问一个线程。它看起来像:

public class MyThread extends Thread () {
  private static MyThread _me;

  private MyThread() { /* make constructors private it can only be made by getting an instance */ }

  public static MyThread getInstance() {
    if(_me == null) {
      _me = new MyThread();
    }
    return _me;
  }
}

其次,调用 doStuff() 将在调用线程中运行。在 Java 线程中,所有线程的处理都发生在 run() 方法中。

最后,如果线程不需要立即执行,您可能希望查看实现等待和通知,或者定时等待。

于 2013-03-29T16:39:01.743 回答