0

これは Android プログラミングへの私の最初の本格的な進出ですが、もっと Java の問題を抱えているように感じます。ScheduledThreadPoolExecutor がどのように機能するかについてのある種の大きな誤解です (ただし、AnimatedSprites の AndEngine の問題であるという考えを喜んで受け入れます)。 、 それも)。基本的には、onFling が発生するまでスプライトを静止させたいと考えています。スプライトがアニメーション化し、1 秒後に再び停止します。ユーザーは、水の中をスプライトを「泳ぐ」ためにフリングを続けなければなりません。私が抱えている問題は、アニメーションにあります。1 秒のタイムスパンに複数の Fling がある場合、アニメーションは停止する前に 1 つまたは 2 つのフレームのみを表示し、「アニメーションを停止する」タスクが積み重なっているように感じます。私' これらすべてが機能するようになったら、Flings が十分に長く、正しい方向に向いていることを確認します。ScheduledThreadPoolExecutor を最初にインスタンス化するとき、プール サイズ 1 を提供します。これは、私の理解では、一度に複数のタスクをキューに入れることはできないことを意味します。その上、.schedule() を呼び出す前に、.remove() タスクを実行して、そこに何もないことを確認します。これは単純なことだと思いますが、これを適切に使用する方法について誤解しているだけです。コードの関連部分をここに貼り付けます。そこに何もないことを確認するだけです。これは単純なことだと思いますが、これを適切に使用する方法について誤解しているだけです。コードの関連部分をここに貼り付けます。そこに何もないことを確認するだけです。これは単純なことだと思いますが、これを適切に使用する方法について誤解しているだけです。コードの関連部分をここに貼り付けます。

...

private ScheduledThreadPoolExecutor shed = new ScheduledThreadPoolExecutor(1);
private Runnable slowDown = new Runnable(){
    public void run(){
        if (eelSprite.isAnimationRunning())
            eelSprite.stopAnimation(0);
    };
};

...

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {

    shed.remove(slowDown);
    shed.schedule(slowDown, 1000, TimeUnit.MILLISECONDS);

    if (!(eelSprite.isAnimationRunning()))
        eelSprite.animate(frame_duration, 0, 12, true);

return false;
}
4

1 に答える 1

0

その質問はトリッキーな主題に触れています。ExecutorService最初のコメントとして、 を扱うときは、おそらく実装ではなくインターフェイスへのコーディングに固執する必要があることを強調したいと思います。これにより、やろうとしていることの複雑さの一部を避けることができます。

適切な例として、公開されているがインターフェイスには存在しない remove() メソッドの使用について言及してい(Scheduled)ExecutorServiceます。つまり、これを使用すると、完全に制御できない実装固有の動作が発生する可能性があります。

の remove メソッドの Javadoc からThreadPoolExecutor:

/**
 * Removes this task from the executor's internal queue if it is
 * present, thus causing it not to be run if it has not already
 * started.
 *
 * <p> This method may be useful as one part of a cancellation
 * scheme.  It may fail to remove tasks that have been converted
 * into other forms before being placed on the internal queue. For
 * example, a task entered using {@code submit} might be
 * converted into a form that maintains {@code Future} status.
 * However, in such cases, method {@link #purge} may be used to
 * remove those Futures that have been cancelled.
 *
 * @param task the task to remove
 * @return true if the task was removed
 */

実装に関する部分は、渡したものを別のフォームに変換する可能性があることに注意してください。これにより、作業を送信するために使用したのと同じインスタンスをRunnable渡すと、remove() メソッドが機能しなくなります。Runnableさらに、削除が機能するという保証はないことに注意してください。すべては、タスクが既に開始されているかどうかに依存します。その場合、競合状態を確認する必要があります。したがって、この特定の方法を使用しないことをお勧めします。

のインスタンス化についてはScheduledThreadPoolExecutor、javadoc も読み間違えている可能性があります。まず、可能な限りExecutors、プールを作成するクラスによって提供されるファクトリ メソッドに固執します。状態の javadoc Executors.newScheduledThreadPool(int):

/**
 * Creates a thread pool that can schedule commands to run after a
 * given delay, or to execute periodically.
 * @param corePoolSize the number of threads to keep in the pool,
 * even if they are idle.
 * @return a newly created scheduled thread pool
 * @throws IllegalArgumentException if {@code corePoolSize < 0}
 */

つまり、int 引数は「コア プール サイズ」です。ここではコアがキーワードです。実装にドリルダウンすると、実際にはスニペットで呼び出したのと同じメソッドが使用されるため、実際には変更はありません。ここで読む時間を少し節約していますが、「コア」プールサイズは、プール内で維持されるスレッドの最小数です (いったん開始されると、プールは通常、事前にスレッドを作成しませんが、それは実装であり、私が思い出す限り契約ではありません)。これは、スレッドの最大数とは関係ありません。実際、さらに掘り下げると、使用したコンストラクターが最終的に無制限のプールを構築し、必要な数のスレッドを生成できることがわかります。

その結果、プールにサブミットしたジョブが同時に実行される場合があります。シングル スレッド プールが必要な場合は、Executors.newSingleThreadedScheduledExecutorファクトリ メソッドを使用することをお勧めします。

最後に、ジョブキャンセルのニーズがあります。では、送信されたジョブをキャンセルするにはどうすればよいでしょうか。ジョブを送信すると、ExecutorServiceインスタンスは通常、Futureオブジェクトを返します。このFutureオブジェクトにはキャンセル ロジックが組み込まれています。サブミットされたジョブにキャンセルフラグを設定できます (まだ開始されていない場合は実際に実行されなくなります)。また、既に開始されている場合は、スレッドの中断を引き起こすこともできます。

これでセマンティクスが少し明確になったことを願っています。

于 2013-03-07T16:17:41.233 に答える