2013-03-07 4 views
0

Это мой первый реальный шаг в программировании на Android, но я чувствую, что у меня больше проблемы с Java - какое-то серьезное недоразумение о том, как работает ScheduledThreadPoolExecutor (хотя я готов чтобы развлечь идею о том, что это проблема AndEngine с AnimatedSprites тоже). По сути, я хочу, чтобы спрайт был неподвижным до тех пор, пока не произойдет onFling. Анимация спрайта, а через секунду - снова. Пользователь должен оставить Fling-ing «плаванием» спрайта через воду. У меня проблема с анимацией. Если у вас более одного Fling в течение 1 секунды, анимация отображает только один или два кадра перед остановкой, и кажется, что задачи «остановить анимацию» сложены. Я проверю и сделаю так, чтобы Flings были достаточно длинными и в правильном направлении после того, как я заработал все это. Когда я впервые создаю экземпляр ScheduledThreadPoolExecutor, я предлагаю ему размер пула 1, который, насколько мне известно, означает, что он не может иметь более одной задачи, сидящей в очереди за раз. Кроме того, прежде чем я вызову задачу .schedule(), I .remove(), просто убедитесь, что там ничего нет. Я уверен, что это что-то простое, просто какое-то недоразумение у меня есть о том, как правильно использовать это. Я вставлю соответствующие части кода здесь:с помощью ScheduledThreadPoolExecutor для многократного планирования задач для AndEngine

... 

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; 
} 

ответ

0

Вопрос затрагивает сложную тему. В качестве первого комментария я хотел бы подчеркнуть, что при работе с ExecutorService вы, вероятно, должны придерживаться кодирования для интерфейсов, а не для реализации. Это должно избежать некоторой сложности того, что вы пытаетесь сделать.

В данном случае вы указываете использование метода remove(), который является общедоступным, но не присутствующим в интерфейсе (Scheduled)ExecutorService. Это означает, что использование этого, вероятно, влечет за собой определенное поведение конкретной реализации, которое вы не можете полностью контролировать.

Из Javadoc метода REMOVE на 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 вы передаете в другую форму, что делает его невозможным для метода удалить() работать при вы передаете ему тот же экземпляр 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} 
*/ 

Что означает ИНТ аргумент является «размером основного пула». Здесь ключевое слово - ключевое слово. Если вы переходите к реализации, он фактически использует тот же метод, который вы вызывали в своем фрагменте, поэтому на самом деле никаких изменений здесь нет. Я сохраняю вам немного чтения здесь, но размер «основного» пула - это минимальное количество потоков, которые будут поддерживаться в пуле (как только они будут запущены, пул обычно не превентивно создает потоки, но это реализация, а не контракт, насколько я помню). Это не имеет никакого отношения к максимальному количеству потоков. На самом деле, если вы еще больше развернетеся, вы увидите, что созданный вами конструктор в конечном итоге построит неограниченный пул, который может порождать столько потоков, сколько необходимо.

Как следствие, задания, которые вы отправляете в пул, могут выполняться одновременно.Если вам нужен однопоточный пул, вы можете использовать фабричный метод Executors.newSingleThreadedScheduledExecutor.

И, наконец, есть необходимость отмены работы. Итак, как отменить работу, которая была подавлена? Ну, когда вы отправляете задание, ExecutorService экземпляров обычно возвращают объект Future. Этот объект Future имеет встроенную логику отмены. Это позволяет вам установить флаг отмены на отправленном задании (что не позволит ему активироваться, если он еще не запущен), и если он уже запущен, он также может спровоцировать прерывание потока.

Надеюсь, что это немного разъяснило семантику.

+0

Ничего себе, столько всего для простого недоразумения. Я надеялся на «о, ты просто забыл ...» Это отличное объяснение, и я ценю время, которое ты вложил в него. Похоже, я кое-что прочитал. Исполнители явно не работают вообще, как я думал, они это сделали. – NickGlowsinDark

Смежные вопросы