Вряд ли я понимаю многопоточность. И, начав изучать его, я столкнулся с одной проблемой, которая пришла мне в голову. Недавно я написал одно простое приложение, и как только я получу новые знания о Java, я хочу улучшить свое приложение с помощью того, что узнал.
Это похоже на простой графический интерфейс, который обновляет изображения каждый период времени. Я реализовал ActionListener и переопределил actionPerformed метод. Таймер с задержкой 15 мс, перекрасил JPanel класс и все заработало нормально. Но я думал, что обновление моего GUI с использованием таймера непосредственно в actionPerformed (я предполагаю, что это другой поток, но я почти не уверен) - плохая идея. Поэтому я решил изменить код и использовать SwingWorker. Я вызвал все свои методы для анимации внутри process () .. и снова приложение работало нормально, но оно стало очень медленным.
Теперь я думаю, что не так? Почему он действует медленнее, чем раньше? Моя задержка таймера на самом деле не ждет 15 мс, она намного медленнее, хотя задержка такая же. Я ошибся с многопоточностью?
Помоги мне понять это. Заранее спасибо
public class GameEngine() extends SwingWorker<Void, Drawable>
GamePanel gp; // ref to JPanel class
{
public GameEngine(GamePanel gp)
{
this.gp = gp;
}
}
protected void doInBackground()
{
publish();
}
protected void process(List<Drawable> chunks)
{
Timer timer = new Timer(15, e ->
{
//methods for animation
fall();
animate();
checkTouch();
});
}
Какой-то код, который я оставил за пределами. Если вам это нужно, я могу написать ...
EDITION
Просто для ясности своей проблемы я приведу еще несколько примеров и дополнительное объяснение.
** Раньше было: **
public class GamePanel extends JPanel
{
public void GamePanel()
{
GameEngine engine = new GameEngine(this);
}
//some images , variables etc...
protected void paintComponent(Graphics g)
super.paintComponent(g)
g.drawImage(image1, x, y, null);
g.drawImage(image2, w, z,null);
...
}
public class GameEngine () implements ActionListener
{
GamePanel gp;
Timer timer;
public void GameEngine(GamePanel gp)
{
this.gp = gp;
timer = new Timer( 15 , this );
}
public void actionPerformed()
{
//these methods repaint my GamePanel every 15ms.
fall(); // make object (image) increment on Y Axis
animate(); // make another object (image) decrement on X Axis
checkTouch(); // check if objects collided
}
}
** Стал: **
public class GamePanel extends JPanel
{
public void GamePanel()
{
GameEngine engine = new GameEngine(this);
}
//some images , variables etc...
protected void paintComponent(Graphics g)
super.paintComponent(g)
g.drawImage(image1, x, y, null);
g.drawImage(image2, w, z,null);
...
}
public class GameEngine () extends SwingWorker<Void, Drawable>
{
GamePanel gp;
Timer timer;
public void GameEngine(GamePanel gp)
{
this.gp = gp;
}
protected void doInBackground()
{
process();
}
protected void progress()
{
timer = new Timer (15, e->
{
new ActionListener(new actionPerformed)
{
//these methods repaint my GamePanel every 15ms.
fall(); // make object (image) increment on Y Axis
animate(); // make another object (image) decrement on X Axis
checkTouch(); // check if objects collided
}
});
}
protected void done()
{
};
}
Когда я впервые его создал, я реализовал ActionListener и обновил свою панель с помощью таймера, объявленного в конструкторе. Я предположил, что он не защищен от потоков.
Вот почему я передаю все в процессе метод, где я объявил таймер, который ActionListener в качестве лямбда-аргумента.
Другими словами, я вызываю все методы для анимации в другом потоке.
Наконец это стало медленнее, по сравнению с первым примером ..
Я не понимаю
- Таймер из первого примера EDT или другой поток?
- Мой первый пример - потокобезопасен?
- Почему мой второй пример идет намного медленнее, чем первый?
Я слышал о НЕ обновлении вашего GUI за пределами EDT, это так?