2010-08-31 2 views
4

Я работаю над программой Java, которая содержит много анимаций как часть пользовательского интерфейса. Каждая анимация требует, чтобы был вызван метод repaint, чтобы анимация произошла. Мне просто интересно, было ли неплохо программировать отдельный поток для каждой анимации, каждый из которых будет ссылаться на их соответствующие методы перерисовки.Можно ли использовать Thread для каждой анимации в Java-программе?

+0

Итак, у вас есть несколько независимых анимированных компонентов на одном экране? – Justin

ответ

1

Нет, потому что накладные расходы всех этих потоков сделают процесс неэффективным.

1

Я предполагаю, что вы используете Swing? Хотя я не уверен.

Я предлагаю прочитать http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html и искать дополнительную информацию о потоках в Swing. В общем случае единственным потоком, который должен обновить GUI, должен быть поток Event Dispatch, хотя есть несколько исключений.

Я думаю, что использование потоков хорошо, просто попросить диспетчерский Event нить, чтобы обновить пользовательский интерфейс,

т.е.

java.awt.EventQueue.invokeLater(new Runnable() 
    { 

     public void run() 
     { 
      //this codes runs on the event dispatch thread 
     } 
    }); 
+1

Примечание: 'SwingUtilities' имеет свою команду' invokeLater'. Я предполагаю, что это просто форвард для версии EventQueue, но я не уверен ... но он позволяет вам использовать его, не набирая пакет EventQueue или импортировать его, даже если это не так, поскольку вы скорее всего импортируете javax.swing. – Powerlord

2

No. Или да, в зависимости от того, что вы делаете.

Как правило, только поток SwingEvent должен рисовать на экране, как правило, в ответ на repaint(). Тем не менее, может быть, что для каждой анимации может быть другой поток для вычисления растрового изображения, которое должно быть нарисовано для каждой анимации, но не нарисовать его, а затем запустить поток SwingEvent, чтобы нарисовать его. Это не имеет смысла, если анимации все синхронны друг с другом, или если количество вычислений связано тривиально.

Если у вас много потоков, будет штраф за исполнение. Я не знаю, какое наказание будет за ваше приложение - вам придется экспериментировать, если вы действительно хотите это знать.

Помните, что несколько потоков будут сложнее программировать (по сравнению с тем, что один поток выполняет работу последовательно), и что с большим количеством потоков (выше количества ядер вашего процессора) почти никогда не позволяет выполнять больше работы в заданном время.

+0

Это хороший ответ. Похоже, что имеет смысл иметь один поток, свернувшийся в фоновом режиме, для создания кадров перед их отображением. –

0

Для swing Лучше всего использовать один (или более) javax.swing.Timer (s). Позвольте переименовать таймер на всех ваших компонентах, нуждающихся в обновлении (анимации). Вы можете создать один пользовательский таймер, который позволит вам добавлять/удалять компоненты. Но будьте осторожны со всеми задействованными потоками. (Вы не хотите проблем с блокировкой/синхронизацией.) Все таймеры используют один и тот же поток для ожидания и запускают код в потоке диспетчеризации событий.

0

Я знаю, что видел некоторые рамки, которые делают эту точную вещь, проверьте JGoodies анимационную библиотеку; I думаю вот где я его видел.

Как правило, идея состоит в том, чтобы свести к минимуму количество потоков (при условии, что анимационные обновления бывают быстрыми, например, переход на уже загруженное изображение), вы можете создать клиентский интерфейс анимации, который один поток анимации вызывает метод обновления в EDT для все клиенты, нуждающиеся в его:

public interface AnimatedComponent { 
public int getInterval(); // how many milliseconds between frames 
public long getLastUpdateTime(); 
public void updateAnimation(); // invoked within the swing EDT 
} 

Всякий раз, когда вы добавляете анимированный компонент, который вы должны зарегистрировать его с центральной анимацией нитью, которая обходит список AnimatedComponent (ов), вызывая updateAnimation при необходимости.

public void updateAllAnimations() { 
long nowTime = System.currentTimeMillis(); 
for (AnimatedComponent c : someList) { 
    if (c.getLastUpdateTime() - nowTime >= c.getInterval()) { 
    c.updateAnimation(); 
    c.repaint(); 
    } 
} 
} 

Вы должны запланировать это на качелях EDT из потока таймера периодически (2-3 раза в секунду, в зависимости от того, как быстро ваша анимация, как ожидается, обновление).

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