2010-01-01 8 views
0

Mon programme est un client connecté à plusieurs serveurs. Je sauve des objets de connexion à tous les serveurs dans un objet carte statique:Synchronisé dans un thread Java

server1 -> Connection1
serveur2 -> Connection2
serverN -> connectionN

public class CacheConnection { 

    private final static Map cacheConnection = new HashMap(); 

    public static void add(String serverName, Socket sock) { 
     synchronized (cacheConnection) { 
      cacheConnection.put(serverName, sock); 
     } 
    } 

    public static Socket get(String serverName) { 
     return (Socket) cacheConnection.get(serverName); 
    } 

    .. 
} 

J'ai beaucoup de threads obtenir des connexions de cette carte pour communiquer avec les serveurs. Comment puis-je m'assurer qu'une connexion ne peut être utilisée que par un thread à la fois? Par exemple, je veux être sûr que le fil 1 et le fil 2 ne peuvent utiliser la connexion 1 en même temps. Par exemple, je veux être sûr que le fil 1 et le fil 2 ne peuvent pas utiliser la connexion 1 en même temps.

+1

Qu'est-ce qu'un serveur multiple? – SLaks

+0

mon programme se connecter à plusieurs serveurs – QuanNH

+0

Vous utilisez serversocket pour le serveur? – SjB

Répondre

3

Je ne suis pas complètement sûr, ce que vous voulez. Je suppose que vous voulez garantir qu'un seul thread à la fois accède à un serveur particulier.

Si votre connexion est quelque chose comme une prise, vous pouvez l'utiliser comme un verrou dans un synchronization statement:

private void send(Connection c, Data d) { 
    synchronized (c) { 
    // for each connection object, only one thread may be inside this block. 
    // all other threads wait until the thread currently in this block exits it. 
    c.send(d); 
    } 
} 

// somewhere else ... 

Data data = determineDataToSend() 
Connection connection = map.get(key); 
send(connection, data) 

Vous pouvez mettre la logique aussi dans un décorateur pour la connexion. Ceci est particulièrement utile si votre connexion a plus d'une méthode envoyer ou recevoir (par exemple, parce que vous utilisez un niveau d'abstraction plus élevé, comme RMI):

public interface PowerfulConnection { 
    public void doA(); 
    public int doB(ParameterForB param); 
} 

public class ConnectionImpl implements PowerfulConnection { 
    // handles the actual connection 
} 

/** 
* This method is a decorator for PowerfulConnection that synchronizes all method accesses. 
*/ 
public class SynchronizedConnection implements PowerfulConnection { 
    private PowerfulConnection target; 

    public SynchronizedConnection(PowerfulConnection target) { 
    if (target == null) throw new NullPointerException(); 
    this.target = target; 
    } 

    public synchronized void doA() { 
    target.doA(); 
    } 

    public synchronized int doB(ParameterForB param) { 
    return target.doB(param); 
    } 
} 

Si vous utilisez l'approche de décorateur, alors la seule chose que vous besoin de changer est la création de l'instance. Au lieu de:

private void connect(key, connectionParams) { 
    map.put(key, new ConnectionImpl(connectionParams)); 
} 

utilisation

private void connect(key, connectionParams) { 
    map.put(key, new SynchronizedConnection(new ConnectionImpl(connectionParams))); 
} 
+0

c'est exactement ce que je veux, merci :) – QuanNH

0

Ou, dans votre premier exemple, la méthode get pourrait simplement supprimer la connexion de la carte. Bien sûr, cela signifie que le client devra être sûr (probablement dans un bloc finally, pour appeler à nouveau, une fois terminé)

Ensuite, attendez et notifiez les boucles lorsqu'un client vient demander une connexion, et Ce n'est pas là.