/ / Czy ta prosta klasa Swing jest bezpieczna dla wątków? - Java, swing, bezpieczeństwo wątku

Czy ta prosta klasa Swing jest bezpieczna dla wątków? - Java, swing, bezpieczeństwo wątku

Tworzę grę typu proof-of-concept w Javie ipostanowiłem (dla praktyki, ale przede wszystkim dla zabawy) stworzyć własny prosty komponent z podwójnie buforowanym bezpiecznym wątkiem. Jednak nie jestem bardzo doświadczony, jeśli chodzi o współbieżność (szczególnie w odniesieniu do Swing) i zastanawiam się, czy są jakieś problemy z moją implementacją, których mi brakowało.

Wdrażanie w następujący sposób:

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class GamePanel extends JPanel
{

private static final long serialVersionUID = 1L;

private BufferedImage mBackImage = null;
private BufferedImage mFrontImage = null;

public BufferedImage getBackImage ()
{
return mBackImage;
}

public void swap ()
{
BufferedImage new_back;
//
synchronized (this)
{
new_back = mFrontImage;
mFrontImage = mBackImage;
}
//
int width = getWidth (), height = getHeight ();
if (width > 0 && height > 0)
{
if (new_back == null || new_back.getWidth () != width
|| new_back.getHeight () != height)
new_back = new BufferedImage (width, height,
BufferedImage.TYPE_INT_ARGB);
//
mBackImage = new_back;
}
else
mBackImage = null;
}

@Override
public void paintComponent (Graphics g)
{
synchronized (this)
{
if (mFrontImage == null)
super.paintComponent (g);
else
g.drawImage (mFrontImage, 0, 0, null);
}
}

}

Zakładam to getBackImage() i swap() zostanie wywołany tylko przez pojedynczy wątek (wątek pętli gry). Farby są wyzwalane przez zegar Swing, a więc są w EDT. Wierzę, że proste bloki zsynchronizowane wokół wykorzystania mFrontImage powinno wystarczyć, aby chronić przed niechcianym zachowaniem, pozwalając wątkowi pętli gry renderować się na obraz z tyłu i wywoływać swap bez martwienia się o odświeżanie Swinga. Czy czegoś brakuje?

Odpowiedzi:

1 dla odpowiedzi № 1

W wątku gry:

BufferedImage image = gamePanel.getBackPanel();
gamePanel.swap();

Twój program będzie teraz w stanie, w którymEvent Dispatch Queue i wątek gry mogą uzyskać dostęp do tego samego obrazu. Oznacza to, że podczas rysowania obrazu podczas rysowania obrazu na ekranie mogą być rysowane śmieszne rzeczy.

Do celów czytania i pisania doPole frontImage samo w sobie jest bezpieczne, ponieważ cały dostęp odbywa się w blokach synchronizowanych, jednak metoda paintComponent może być lepiej napisana, aby zmniejszyć ilość czasu spędzonego w zsynchronizowanym bloku.

@Override
public void paintComponent (Graphics g)
{
BufferedImage localFrontImage;
synchronized (this)
{
localFrontImage = mFrontImage;
}
if (localFrontImage == null)
super.paintComponent (g);
else
g.drawImage (localFrontImage, 0, 0, null);

}

1 dla odpowiedzi nr 2
  • Swing to czysty pojedynczy gwint i wszystkie zdarzenia muszą być wykonane na EDT, wtedy nie widzę powodu synchronized (this)

  • posługiwać się Ikona w JLabel do dispaying Obrazy w GUI Swing

  • dla każdego z swap"s types, spójrz na CardLayout