0

这是我第一次真正涉足 Android 编程,但我觉得我遇到了更多的 Java 问题——对 ScheduledThreadPoolExecutor 的工作方式存在某种重大误解(尽管我愿意接受它是 AnimatedSprites 的 AndEngine 问题的想法, 也)。本质上,我希望精灵在 onFling 发生之前是静止的。精灵动画,一秒钟后,再次停止。用户必须保持 Fling-ing 才能使精灵在水中“游动”。我遇到的问题是动画。如果在 1 秒的时间跨度内有多个 Fling,动画在停止前只显示一两帧,感觉就像“停止动画”任务在叠加。一世' 在我完成所有这些工作后,我会检查并确保 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 回答