ArrayList在另一个线程中为空

时间:2016-03-28 21:24:44

标签: java multithreading list

我试图为我的游戏做一台服务器,负责验证和配对。

我有一个房间的ArrayList(房间只跟踪游戏中的玩家列表),我用它来进行配对。

我有两个单身,PoulpiciousServer.java是主要类,它运行一切,而MatchmakingEngine运行在另一个线程上,并处理要求有空间玩的玩家。

以下是课程(我使用KryoNet):

package com.poulpicious.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Server;
import com.poulpicious.network.packets.Packet00Login;
import com.poulpicious.network.packets.Packet01LoginAcknowledge;
import com.poulpicious.network.packets.Packet02CharacterInfos;
import com.poulpicious.network.packets.Packet03CharacterInfosResponse;
import com.poulpicious.network.packets.Packet04RequestMatchmaking;
import com.poulpicious.network.packets.Packet05MatchmakingResponse;
import com.poulpicious.network.packets.Packet06StopMatchmaking;

public class PoulpiciousServer {

    private static class PoulpiciousServerHolder {
        private static final PoulpiciousServer _instance = new PoulpiciousServer();
    }

    public static PoulpiciousServer get() {
        return PoulpiciousServerHolder._instance;
    }

    private Server server;

    private Map<Integer, ServerPlayer> serverPlayers = new HashMap<Integer, ServerPlayer>();
    private List<Room> rooms;

    private Thread matchmakingEngineThread;

    public PoulpiciousServer() {
        this.server = new Server();
        this.rooms = Collections.synchronizedList(new ArrayList<Room>());

        Kryo k = this.server.getKryo();
        k.register(Packet00Login.class);
        k.register(Packet01LoginAcknowledge.class);
        k.register(Packet02CharacterInfos.class);
        k.register(Packet03CharacterInfosResponse.class);
        k.register(Packet04RequestMatchmaking.class);
        k.register(Packet05MatchmakingResponse.class);
        k.register(Packet06StopMatchmaking.class);
    }

    public void run() {
        try {
            this.rooms.add(new Room());
            server.addListener(new PoulpiciousServerListener(this));

            this.matchmakingEngineThread = new Thread(MatchmakingEngine.get(), "matchmaking");
            this.matchmakingEngineThread.start();

            server.start();
            server.bind(25565, 25565);

            System.out.println("Master server started.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void registerPlayer(Connection c, String username) {
        this.serverPlayers.put(c.getID(), new ServerPlayer(c, username));
    }

    public static void main(String[] args) {
        new PoulpiciousServer().run();
    }

    public ServerPlayer getServerPlayer(int connID) {
        return this.serverPlayers.get(connID);
    }

    public Room getRoom(int index) {
        synchronized (rooms) {
            return this.rooms.get(0);
        }
    }

    public List<Room> getRooms() {
        return rooms;
    }

}

和配对引擎:

package com.poulpicious.server;

import java.util.ArrayList;

import com.poulpicious.network.packets.Packet05MatchmakingResponse;

public class MatchmakingEngine implements Runnable {

    private static class MatchmakingEngineHolder {
        private static final MatchmakingEngine _instance = new MatchmakingEngine();
    }

    public static MatchmakingEngine get() {
        return MatchmakingEngineHolder._instance;
    }

    private boolean running;

    private ArrayList<ServerPlayer> playersSearching = new ArrayList<ServerPlayer>();

    public MatchmakingEngine() {
        this.running = true;
    }

    @Override
    public void run() {
        while (running) {
            if (PoulpiciousServer.get().getRooms().size() > 0)
                System.out.println(PoulpiciousServer.get().getRooms().size());

            synchronized (playersSearching) {
                // System.out.println(playersSearching.size());
                if (playersSearching.size() > 0) {
                    System.out.println("Matching a player");
                    ServerPlayer current = playersSearching.get(0);

                    PoulpiciousServer.get().getRoom(0).addPlayer(current);

                    Packet05MatchmakingResponse pmr = new Packet05MatchmakingResponse();
                    pmr.nbPlayers = PoulpiciousServer.get().getRoom(0).getPlayerCount();
                    current.getConnection().sendTCP(pmr);
                    playersSearching.remove(0);
                }
            }
        }
    }

    public void registerPlayer(ServerPlayer player) {
        synchronized (playersSearching) {
            this.playersSearching.add(player);
        }
    }

}

所以在主课程中我添加了一个新房间,仅供测试,所以房间列表至少包含一个房间。

在匹配引擎中,在run方法中,我想打印此列表的大小,但它没有,因为列表为空。

问题是我不会在任何地方清空这个列表,而且我不明白为什么它在另一个帖子中是空的。

我使用了synchronized,Collections.synchronizedList,甚至是ConcurrentMap进行测试,没有工作......

我怎样才能确定该列表是否真的是线程安全的,并且没有任何理由不清空?

1 个答案:

答案 0 :(得分:2)

brew install gcc不是单身人士:

  • 您在PoulpiciousServer
  • 中创建了一个实例
  • 您在PoulpiciousServerHolder方法
  • 中创建了一个实例

您只能在PoulpiciousServer.main方法中创建的内容上调用PoulpiciousServer.run()

您可以访问由main返回的实例中的房间列表,PoulpiciousServer.get()类是由PoulpiciousServerHolder类创建的实例。这个从未添加任何房间,因为它的run()方法永远不会被调用。

new PoulpiciousServer()方法中的main替换为PoulpiciousServer.get()