等待具有相同服务的其他线程达到某一点

时间:2013-11-28 21:40:17

标签: java multithreading

我有一个多人网络游戏,我用Java编写,玩家连接到服务器并获得他们可以玩的“卡片”,每个玩家都有自己的线程中产生的服务来处理所有事情。 我想要做的是找出让服务器'暂停'的方法,直到所有玩家都已连接并达到服务中的相同点,这样游戏才能开始。

服务器产生如下线程:

for (int i = 1; i <= numPlayers; i++){
    ArrayList<Card> playersCards = getPlayersCards(i-1);    
    Socket s = server.accept();
    System.out.println("Player "+ i +" connected.");
    Service service = new Service(s, playersCards);
    Thread t = new Thread(service);
    t.start();
}

然后我的服务:

public class Service implements Runnable {

    private Socket s;
    private Scanner in;
    private PrintWriter out;
    private ArrayList<Card> cards;


    public Service(Socket aSocket, ArrayList<Card> cards) {
        s = aSocket;
        this.cards = cards;
    }

    public void run() {
        try {
            in = new Scanner(s.getInputStream());
            out = new PrintWriter(s.getOutputStream());
            out.println("Welcome to the Simple Stock Market Game.");
            out.flush();
            sendCards();
            //AT THIS POINT THE SERVICE WOULD NEED TO wait for all players to connect
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.println("Thanks for playing the Simple Stock Market Game.");
            out.flush();
        }
        try {
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Player disconnected."); 
    }

    private void sendCards() {
        Gson gson = new Gson();
        String cardsJSON = gson.toJson(cards);
        out.println(cardsJSON);
        out.flush();    
    }

}

现在我假设我可以通过该服务将有多少玩家,并等待那么多线程达到这一点? 不太确定,希望你们能帮忙!

2 个答案:

答案 0 :(得分:2)

您可以使用java.util.concurrent.CountDownLatch,这正是您所需要的。

在创建服务的循环之前,使用预期的线程数(玩家)初始化它:

CountDownLatch playersLatch = new CountDownLatch(numPlayers);

然后在服务中:

playersLatch.countDown();
try {
    playersLatch.await();
} catch (InterruptedException ex) {
    //handle interruption
}

此外,您可能希望查看java.util.concurrent.CyclicBarrier,它类似但在等待线程释放后允许重用。

答案 1 :(得分:0)

如果你反复调用它,Phaser将是最好的解决方案,因为它以简单和可重用的方式组合了CountDownLatch和CyclicBarrier。对于一次性使用,CyclicBarrier就足够了(与Phaser相比性能略有提升)。

另外请记住,如果您使用这样的同步工具,则在出错时(在最终代码中)取消注册,否则所有剩余的方将被无限期停留。