Java 从线程访问数组列表

Java 从线程访问数组列表,java,multithreading,arraylist,static,network-programming,Java,Multithreading,Arraylist,Static,Network Programming,我正在为我的网络课制作一个多人冒险游戏。我有一个客户机和一个服务器,服务器是多线程的,只要连接了一个新客户机,它就会启动一个新线程。我有一个数组列表来跟踪玩家,以确保不会添加新玩家。出于某种原因,当一个新客户机连接时,它会取代旧客户机,并填充一个新的位置。这是我这部分的代码 public class ClientHandler implements Runnable{ private AsynchronousSocketChannel clientChannel; private static

我正在为我的网络课制作一个多人冒险游戏。我有一个客户机和一个服务器,服务器是多线程的,只要连接了一个新客户机,它就会启动一个新线程。我有一个数组列表来跟踪玩家,以确保不会添加新玩家。出于某种原因,当一个新客户机连接时,它会取代旧客户机,并填充一个新的位置。这是我这部分的代码

public class ClientHandler implements Runnable{
private AsynchronousSocketChannel clientChannel;
private static String command[];
private static String name;
private static GameCharacter character;
public ClientHandler(AsynchronousSocketChannel clientChannel)
{
    this.clientChannel = clientChannel;
}

public void run(){
    try{
        System.out.println("Client Handler started for " + this.clientChannel);
        System.out.println("Messages from Client: ");
        while ((clientChannel != null) && clientChannel.isOpen()) {
            ByteBuffer buffer = ByteBuffer.allocate(32);
            Future result = clientChannel.read(buffer);
            //Wait until buffer is ready
            result.get();
            buffer.flip();
            String message = new String(buffer.array()).trim();
            if(message == null || message.equals(""))
            {
                break;
            }
            System.out.println(message);
            clientChannel.write(buffer);
            try {
                //Add the character to the routing table and the character table
                if (message.contains("connect")) {
                    System.out.println("I'm here too?");
                    command = message.split(" ");
                    name = command[1];
                    AdventureServer.userInfo.put(name, this);
                    //Check to see if this game character exists
                    GameCharacter test;
                    boolean exists = false;
                    for(int i=0; i < AdventureServer.characters.size(); i++)
                    {
                        test = AdventureServer.characters.get(i);
                        System.out.println(test.getName());
                        System.out.println(this.name);
                        if(this.name.equals(test.getName()))
                        {
                            System.out.println("already Here");
                            exists = true;
                        }
                    }
                    if (exists == true)
                    {
                        //This person has connected to the server before
                    }
                    else {
                        //Create a game character
                        System.out.println("didn't exist before");
                        character = new GameCharacter(this.name, World.getRow(), World.getCol());
                        AdventureServer.characters.add(AdventureServer.userInfo.size() - 1, character);
                        System.out.println(AdventureServer.characters.get(0).getName() + " " +AdventureServer.characters.get(1).getName());
                    }
                }
公共类ClientHandler实现可运行{
专用异步socketchannel客户端通道;
私有静态字符串命令[];
私有静态字符串名;
私有静态游戏角色;
公共客户端处理程序(异步socketchannel客户端通道)
{
this.clientChannel=clientChannel;
}
公开募捐{
试一试{
System.out.println(“为“+this.clientChannel”启动的客户端处理程序);
System.out.println(“来自客户端的消息:”);
while((clientChannel!=null)&&clientChannel.isOpen(){
ByteBuffer缓冲区=ByteBuffer.allocate(32);
未来结果=clientChannel.read(缓冲区);
//等待缓冲区准备就绪
result.get();
flip();
字符串消息=新字符串(buffer.array()).trim();
if(message==null | | message.equals(“”)
{
打破
}
System.out.println(消息);
clientChannel.write(缓冲区);
试一试{
//将字符添加到路由表和字符表中
if(message.contains(“connect”)){
System.out.println(“我也在这里?”);
command=message.split(“”);
名称=命令[1];
AdventureServer.userInfo.put(名称,this);
//检查此游戏角色是否存在
配子性状试验;
布尔存在=假;
对于(int i=0;i
我知道底部的打印行会为第一个连接的客户端抛出错误,但这不是问题的一部分。 这是服务器的声明

public class AdventureServer {
public static Map<String, ClientHandler> userInfo = new HashMap<>();
public static World world;
public static List<GameCharacter> characters = Collections.synchronizedList(new ArrayList<>());
public static void main(String args[]) {
    //Create the games map that all of the users will exist on
    world = new World(args[0]);

    System.out.println("Asynchronous Chat Server Started");
    try {
        AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();
        InetSocketAddress hostAddress = new InetSocketAddress("192.168.1.7", 5000);
        serverChannel.bind(hostAddress);
        while (true)
        {
            System.out.println("Waiting for client to connect");
            Future acceptResult = serverChannel.accept();
            AsynchronousSocketChannel clientChannel = (AsynchronousSocketChannel) acceptResult.get();
            new Thread (new ClientHandler(clientChannel)).start();
        }
    } catch (Exception e) {
        System.out.println("error interrupted");
        e.printStackTrace();
        System.exit(0);
    }
}
}
公共类冒险服务器{
public static Map userInfo=new HashMap();
公共静态世界;
public static List characters=Collections.synchronizedList(新的ArrayList());
公共静态void main(字符串参数[]){
//创建所有用户都将存在的游戏地图
世界=新世界(args[0]);
System.out.println(“异步聊天服务器启动”);
试一试{
AsynchronousServerSocketChannel serverChannel=AsynchronousServerSocketChannel.open();
InetSocketAddress主机地址=新的InetSocketAddress(“192.168.1.7”,5000);
绑定(主机地址);
while(true)
{
System.out.println(“等待客户端连接”);
Future acceptResult=serverChannel.accept();
AsynchronousSocketChannel客户端通道=(AsynchronousSocketChannel)acceptResult.get();
新线程(新ClientHandler(clientChannel)).start();
}
}捕获(例外e){
System.out.println(“错误中断”);
e、 printStackTrace();
系统出口(0);
}
}
}
这是我的游戏角色构造器

public class GameCharacter {
public static int xpos;
public static int ypos;
private static String name;
private static int rowSize;
private static int columnSize;
static List<String> inventory = new ArrayList<>();

//Constructor
GameCharacter(String n, int rSize, int cSize)
{
    xpos = 0;
    ypos = 0;
    name = n;
    rowSize = rSize;
    columnSize = cSize;
}

GameCharacter()
{
    xpos = 0;
    ypos = 0;
    name = "billybob";
    rowSize = 10;
    columnSize = 10;
}
公共类游戏角色{
公共静态int XPO;
公共静态int YPO;
私有静态字符串名;
私有静态整数行大小;
私有静态int列大小;
静态列表清单=新的ArrayList();
//建造师
GameCharacter(字符串n,int rSize,int cSize)
{
xpos=0;
ypos=0;
name=n;
行大小=rSize;
columnSize=cSize;
}
游戏角色()
{
xpos=0;
ypos=0;
name=“billybob”;
行大小=10;
列大小=10;
}

关于可读性、可测试性和样式,我还建议您不要直接访问属于另一个类的数据结构

   Adventureserver.characters.add(blah blah)
我建议将字符设置为Adventureserver的私有字段,然后创建一个方法来添加或删除其中的字符。事实上,我倾向于不将字符设置为静态--这没有什么真正的优势,而且在某些情况下,您可能希望运行多个Adventureserver

有点像这样:

public class AdventureServer {
<...>
private List<GameCharacter> characters = Collections.synchronizedList(new ArrayList<>);

<...>
public void addCharacter(GameCharacter char) {
   <... error checking ...>
   characters.add(char);
}
public void removeCharacter(GameCharacter char) {
   <... implementation ... >
}
public boolean isCharacterHere(GameCharacter char) {
}
public List<GameCharacter> getCharacters() {
  <... you could either return characters here, or a copy of it,
   depending upon how paranoid you want to be >
公共类冒险服务器{
私有列表字符=Collections.synchronizedList(新ArrayList);
public void addCharacter(GameCharacter char){
字符。添加(字符);
}
public void removeCharacter(游戏角色字符){
}
公共布尔值isCharacterHere(GameCharacter字符){
}
公共列表getCharacters(){
您可以尝试:

public static volatile List<GameCharacter> characters = Collections.synchronizedList(new ArrayList<>());
致:

或者使HashMap同步:

public static Map<String, ClientHandler> userInfo = Collections.synchronizedMap(new HashMap<>());
游戏角色:

public static int xpos;
public static int ypos;
private static String name;
private static int rowSize;
private static int columnSize;
static List<String> inventory = new ArrayList<>();
publicstaticintxpos;
公共静态int YPO;
私有静态条纹
public static Map<String, ClientHandler> userInfo = Collections.synchronizedMap(new HashMap<>());
private static String command[];
private static String name;
private static GameCharacter character;
public static int xpos;
public static int ypos;
private static String name;
private static int rowSize;
private static int columnSize;
static List<String> inventory = new ArrayList<>();
import java.util.ArrayList;
import java.util.List;

public class GameCharacter {
private int xpos;
private int ypos;
private String name;
private int rowSize;
private int columnSize;

private List<String> inventory = new ArrayList<>();

// Constructor
GameCharacter(String n, int rSize, int cSize) {
    this.xpos = 0;
    this.ypos = 0;
    this.name = n;
    this.rowSize = rSize;
    this.columnSize = cSize;
}

GameCharacter() {
    this.xpos = 0;
    this.ypos = 0;
    this.name = "billybob";
    this.rowSize = 10;
    this.columnSize = 10;
}

public int getXpos() {
    return xpos;
}

public void setXpos(int xpos) {
    this.xpos = xpos;
}

public int getYpos() {
    return ypos;
}

public void setYpos(int ypos) {
    this.ypos = ypos;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getRowSize() {
    return rowSize;
}

public void setRowSize(int rowSize) {
    this.rowSize = rowSize;
}

public int getColumnSize() {
    return columnSize;
}

public void setColumnSize(int columnSize) {
    this.columnSize = columnSize;
}

public List<String> getInventory() {
    return inventory;
}

public void setInventory(List<String> inventory) {
    this.inventory = inventory;
}

}