/ / Ist diese einfache Swing-basierte Klasse Thread-sicher? - Java, Swing, Thread-Sicherheit

Ist diese einfache Swing-basierte Klasse Thread-sicher? - Java, Swing, Thread-Sicherheit

Ich mache ein Proof-of-Concept-Spiel in Java undbeschlossen (zum Üben aber vor allem zum Spaß), meine eigene einfache Komponente mit threadsicherer Doppelpufferung zu machen. Ich bin jedoch nicht sehr erfahren in Sachen Nebenläufigkeit (speziell in Bezug auf Swing) und ich frage mich, ob es irgendwelche Probleme mit meiner Implementierung gibt, die ich vermisse.

Implementierung wie folgt:

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

}

Ich nehme an, dass getBackImage() und swap() wird nur von einem einzigen Thread (dem Game-Loop-Thread) aufgerufen. Die Farben werden über einen Swing-Timer ausgelöst und befinden sich somit im EDT. Ich glaube, dass die einfachen synchronisierten Blöcke um die Verwendung von mFrontImage sollte genug sein, um gegen unerwünschtes Verhalten zu schützen, indem es dem Game-Loop-Thread ermöglicht, auf das Back-Image zu rendern und Swap aufzurufen, ohne sich um die Swing-Neuzeichnungen kümmern zu müssen. Fehle ich etwas?

Antworten:

1 für die Antwort № 1

Im Spielfaden:

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

Ihr Programm wäre jetzt in einem Zustand, in dem dieEvent Dispatch Queue und der Spiel-Thread können auf dasselbe Bild zugreifen. Das bedeutet, dass lustige Dinge auf das Panel gezeichnet werden können, wenn Sie zu dem Bild zeichnen, während das EDT das Bild auf den Bildschirm zeichnet.

Zum Zwecke des Lesens und Schreibens an dieDas Feld frontImage selbst ist dann threadsicher, da alle Zugriffe innerhalb synchronisierter Blöcke ausgeführt werden. Die Methode paintComponent könnte jedoch besser geschrieben werden, um den Zeitaufwand in einem synchronisierten Block zu reduzieren.

@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 für die Antwort № 2
  • Swing ist ein reines single threaded und alle Events müssen auf EDT durchgeführt werden, dann kann ich keinen Grund dafür sehen synchronized (this)

  • benutzen Symbol in dem JLabel zum Anzeigen Bilder in der Swing-GUI

  • für irgendeinen von swap"s typesDu hast es gesehen Kartenlayout