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