2010-01-01 115 views
0

我的程序是連接到多個服務器的客戶端。我的連接對象保存到所有服務器中的靜態映射對象:在Java線程中同步

服務器1 - >連接1
服務器2 - >連接2
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); 
    } 

    .. 
} 

我有很多線程獲得連接從這張地圖上與服務器進行通信。我如何確保連接一次只能由一個線程使用?

例如,我想確保線程1和線程2不能同時使用連接1。

+1

什麼是多服務器? – SLaks 2010-01-01 15:34:26

+0

我的程序連接到很多服務器 – QuanNH 2010-01-01 15:36:46

+0

您使用serversocket作爲服務器嗎? – SjB 2010-01-01 15:37:03

回答

3

我不完全確定,你想要什麼。我假設你要保證一次只有一個線程訪問一個特定的服務器。

如果你的連接是像一個插座,那麼您可以在一個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) 

你可以把邏輯還融入了裝飾進行連接。這是連接是否具有一種以上的方法是發送或接收特別有用的(例如,由於您使用的是更高的抽象水平像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); 
    } 
} 

如果您正在使用的裝飾方法,那麼你的唯一的事需要改變的是實例創建。相反的:

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

使用

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

這正是我想要的,謝謝:) – QuanNH 2010-01-01 16:14:12

0

或者,在最初的例子中,GET方法可以只從地圖中刪除的連接。當然,這意味着客戶端必須確定(可能在finally塊中,完成後再次調用add)

然後等待並通知循環,以便客戶端進入時詢問連接,並且它不在那裏。