0

私は Java ベースのアプリ (Android) を持っており、バックグラウンドで潜在的に長い操作を実行できるようにしたいと考えています。AsyncTask の Android ドキュメントでは、数秒以上実行される可能性のあるタスクにそれらを使用しないようにアドバイスしているため (これはなぜですか?)、代わりに Java の Thread のサブクラスを使用しています。この Thread サブクラス (HPCHeadThread) の目的は、主に、いくつかの非同期制御メカニズムのインスタンスをホストし、他のスレッドが使用するメカニズムへのアクセサー メソッドを提供することです。私が目指しているワークフローは、HPCHeadThread への参照を使用して任意のスレッドから hHPCHeadThread.doStuff() を呼び出すことができ、HPCHeadThread でインスタンス化されたコントロール オブジェクトが HPCHeadThread スレッドでのみそのスレッドで動作するようにすることです。別のスレッドからアクセスされていない場合、HPCHeadThread は CPU サイクルを浪費しないようにスリープする必要があります。

TestActivity.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 スレッド内から hHPCHeadThread.doStuff() を呼び出した場合、作業は HPCHeadThread またはメインの TestActivity スレッドで処理されますか? TestActivity は、独自のスレッド内で順次実行を続行する前に、doStuff() メソッドが戻るのを待ちますか? メソッド呼び出しは、HPCHeadThread をウェイクアップしますか、および/またはループ中に HPCHeadThread の run() メソッドで InterruptedException をスローしますか?

4

2 に答える 2

2

Android のドキュメントでは、システムがメモリを必要とし、アプリがバックグラウンドで実行されているときはいつでもアクティビティがスワップ アウトされる可能性があるため、アクティビティで長時間実行されるスレッドに対してアドバイスしています。

長時間実行されるタスクを実行する場合: それだけを目的とした Service を作成します: より多くのメモリが必要なときにスローされるべきではない長時間実行されるタスク。

待ち行列について: 良いアドバイスのように聞こえます。ブロッキング呼び出しを持つ 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);

これは、ブロックすることなく任意のスレッドから呼び出すことができ、1 つずつ実行されるタスクをキューに追加します。

于 2013-03-29T20:11:14.093 に答える
0

まず、古いシングルトン デザイン パターンを使用して、どこからでも 1 つのスレッドにアクセスできるようにすることができると思います。次のようになります。

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 に答える