views:

99

answers:

2

my program is a client connect to multi server.

i save connection object to all server in a static map object: server1 -> connection1, server2 -> connection2, ..

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

    ..
}

i have many thread get connection from this map to send/receive with server.

my problem:

at a time only one thread uses one connection (that' means: thread 1 & thread 2 can't use connection1 at the same time, for exam)

thanks

Quan

+2  A: 

I am not completely sure, what you want. I assume that you want to guarantee that only one thread at a time accesses one particular server.

If your connection is something like a socket, then you can use it as a lock in a 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)

You can put the logic also into a decorator for the connection. This is especially useful if your connection has more than one mehtod that send or receive (e.g., because you use a higher abstraction level like 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);
  }
}

If you are using the decorator approach, then the only thing you need to change is the instance creation. Instead of:

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

use

private void connect(key, connectionParams) {
  map.put(key, new SynchronizedConnection(new ConnectionImpl(connectionParams)));
}
nd
that's exactly what i want, thank you :)
QuanNH
A: 

or, in your initial example, the get method could just remove the connection from the map.

Of course that means the client would have to be sure (probably in a finally block, to call add again, when done)

then have wait and notify loops for when a client comes in to ask for a connection, and it's not there.

MeBigFatGuy