多线程并通过套接字发送

时间:2018-02-14 17:44:11

标签: java multithreading sockets objectinputstream objectoutputstream

说一个对象,ArrayList<String>由在外部类中运行的多个线程共享(可运行的类是较大类的内部类 - 服务器)。这些线程代表单独的客户端,它们分别具有专用于处理其输出和服务器输入的线程。现在,在线程中创建线程时,添加/删除此ArrayList<String>中的值,该值在加入/退出客户端程序时存储其用户名。 但是,当我将ArrayList<String>发送到每个客户端套接字时,每个客户端都会获得他们之前(当他们第一次加入时)获得的arraylist而不是新的更新列表(当新人加入时)。例如。如果约翰先加入,那么他的名单将始终只包括约翰,如果加入下一个,那么她只会获得约翰,卡斯特的名单,而不会更多。

我的服务器端程序有这个方法发送列表。

public void sendOnlineList() {
    try{

        for(ObjectOutputStream os: clientStreams) { //ObjectOutputStream for each client socket
            System.out.println("sending: " + printAll(currentOnline));
            os.writeObject(currentOnline);
        }
    }catch(IOException e) {e.printStackTrace();}    

}

客户端程序有一个线程可以在需要时不断接收消息。

public class ServReader implements Runnable {
    @SuppressWarnings("unchecked")
    public void run() {
        try {
            Object line = null;

            while((line=is.readObject())!=null) { 
                synchronized(this) {
                if(line instanceof String) { //normal chat message
                    line = (String) line;
                    System.out.println(line);
                    text.append(line + "\n"); //irrelevant stuff using the string
                } else if(line instanceof ArrayList<?>) { //list of users
                    System.out.println("found list");
                    printAll((ArrayList<String>) line);
                    setOnline((ArrayList<String>) line); //irrelevant stuff using the list
                }
                }

            }
            /*String line = null;
            while((line=is.readLine())!=null) {
                text.append(line+ "\n");
                System.out.println(line);
            }*/
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

服务器端程序输出到控制台

sending: John, Cath
sending: John, Cath

但令人惊讶的是,客户端程序输出到控制台

约翰:

found list
John,

蛋白酶:

found list
John, Cath,

我想将相同的列表发送到所有客户端,但不知何故,相同的列表从服务器发送到两个客户端,但每个客户端收到不同的列表;当然,对象在发送时不会发生变化......这段代码中的内容是错误的吗?

1 个答案:

答案 0 :(得分:-1)

所以,如果我理解正确,行为如下:

  • John连接
  • John已添加到列表中
  • John收到当前列表,仅包含{"John"}

同样适用于Cath,但她的名单是{"John", "Cath"}。如果我错了,请纠正我。

JavaDoc for ObjectOutputStream似乎暗示当前对象(如对象状态的副本)通过流发送,并且ObjectInputStream“重建”对象。

这意味着John和Cath只会在您编写该列表时收到该列表的副本。

如果你想在同一个应用程序中共享一个对象(可执行文件/运行时,无论你怎么称呼它),你可以choose a concurrent list/queue并在外层使用public static(或者所有其他地方)课程可以访问)。

如果要通过连接共享和对象,则需要在每次对象更改时发送更新(略微冗余)或让客户端从服务器请求列表(根据具体情况更有效)。 / p>