/ / Cette classe basée sur Swing est-elle thread-safe? - java, balançoire, filet de sécurité

Cette classe simple basée sur Swing est-elle sûre pour les threads? - java, swing, sécurité des fils

Je fais un jeu de preuve de concept en Java etdécidé (pour la pratique mais surtout pour le plaisir) de créer mon propre composant simple avec double tampon sécurisé pour les threads. Cependant, je n’ai pas beaucoup d’expérience en matière de concurrence (surtout en ce qui concerne Swing) et je me demande s’il manque des problèmes lors de l’implémentation.

Mise en œuvre comme suit:

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

}

Je suppose que getBackImage() et swap() ne sera appelé que par un seul fil (le fil de la boucle de jeu). Les peintures sont déclenchées via une minuterie Swing et sont donc dans l'EDT. Je crois que les simples blocs synchronisés autour de l'utilisation de mFrontImage devrait suffire à protéger contre les comportements indésirables, permettant ainsi au fil de la boucle de jeu de restituer l’image arrière et de permuter les appels sans s’inquiéter des répétitions de Swing. Est-ce que je manque quelque chose?

Réponses:

1 pour la réponse № 1

Dans le fil du jeu:

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

Votre programme serait maintenant dans un état où leLa file d'attente d'envoi d'événements et le fil du jeu peuvent accéder à la même image. Cela pourrait signifier des choses amusantes sur le panneau si vous dessiniez sur l'image pendant que le TDE dessinait l'image sur écran.

Aux fins de lecture et d'écriture auSi vous utilisez le champ frontImage seul, vous êtes en sécurité, car tous les accès sont effectués dans des blocs synchronisés. Cependant, la méthode paintComponent pourrait être mieux écrite pour réduire le temps passé dans un bloc synchronisé.

@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 pour la réponse № 2