Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在线程之间使用同步集合_Java_Multithreading_Collections - Fatal编程技术网

Java 在线程之间使用同步集合

Java 在线程之间使用同步集合,java,multithreading,collections,Java,Multithreading,Collections,代码-> 我遇到问题的块 class ClientSender implements Runnable { Socket server; ServerClientFrontEnd SCFE; public ClientSender(Socket server, ServerClientFrontEnd SCFE){ this.server = server; this.SCFE = SCFE;

代码->

我遇到问题的块

class ClientSender implements Runnable {
        Socket server;
        ServerClientFrontEnd SCFE;
        public ClientSender(Socket server, ServerClientFrontEnd SCFE){
            this.server = server;
            this.SCFE = SCFE;
        }

        public void run(){
            try(ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream())){
                //System.out.println("Client chat ver. 0.1");
                //Scanner get = new Scanner(System.in);
                while(!server.isClosed()){
                    //System.out.print("YOU:");
                    if(!SCFE.synchronizedOutputCollection.isEmpty()) // Here
                    {
                        logger.info("Has made it to ClientSender!");
                        String string = SCFE.synchronizedOutputCollection.firstElement();
                        logger.info(string);
                        out.writeObject(string); // Here
                        logger.info("Output Queue: " + SCFE.synchronizedOutputCollection.toString());
                    }
                    //else{ logger.info("It failed the conditional"); }
                }
            } catch (IOException ex) {
                //logger.info("Closing connection...");
                //System.exit(0);
            }
        }
    }
    class ClientReceiver implements Runnable {
        Socket server;
        ServerClientFrontEnd SCFE;
        public ClientReceiver(Socket server, ServerClientFrontEnd SCFE){
            this.server = server;
            this.SCFE = SCFE;
        }

        public void run(){
            try(ObjectInputStream in = new ObjectInputStream(server.getInputStream())){
                while(!server.isClosed()){
                    SCFE.ChatBox.setText(SCFE.ChatBox.getText() + "\nOTHER: " + (String) in.readObject()); //Here
                    logger.info("Receiver has read object!");
                }
                } catch (IOException ex) {
                    logger.info("Closing connection");
                    System.exit(0);
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
由于某种原因,我不能让它工作。我已经让它在命令行环境中工作,非常完美,但我想将它移植到图形用户界面,这个问题已经困扰了我一个多小时。我不知道如何处理客户机的原始类调用其他线程这一事实,我需要这些线程向服务器发送和接收信息

基本上,我的程序的工作原理是让客户端通过ServerSocket连接到服务器,然后ServerSocket处理每个请求。当然,我最近刚刚在周四学习了套接字,但我想做一个自己的程序。。。无论如何,接下来的问题是ServerClientFrontEnd类,出于某种原因,我不知道如何使用我的一生,我用来获取输入文本的集合要么保持为空,要么就是无法从中读取

也许这与我的while循环有关,但它以前工作得很好。我到处都有大量的记录器来记录一切,如果在检查集合是否为空时添加else语句,它肯定会反复激活else语句,即使在synchronizedOutputCollection被赋予一个值之后也是如此。事实上,我甚至在按下send按钮时打印集合内部的值。事实上,当我在线程中尝试一个类似的print语句时,集合是空的,并且仍然是空的

如何在线程之间共享对象的同步集合?这个问题困扰着我,我非常感谢你的回答


这也是可运行的,您只需激活服务器和2个客户端即可进行测试。另外,我尝试过阻止队列,但它们会使GUI线程冻结,因为从来没有读取队列,从而导致死锁。

正如@markspace在一篇评论中指出的,您的代码中有很多有趣的事情。您应该后退一步,回到命令行界面,重新设计整个类结构。删除这些内部类,使用一些接口,如

MessageListener
connectionlistener
,您的客户端或服务器使用这些接口与其他类(如GUI)讨论收到的消息或创建/丢失的连接等问题

完成后,客户端的主要方法应该非常简单:

public static void main(String [] args) {
    Client client = new Client("127.0.0.1");
    client.addMessageListener(new MessageListener() {
        public void messageRecieved(String message) {
            System.out.println(message);
        }
    });

    client.connect();
    System.out.println("Connected to server.");
    Scanner scanner = new Scanner(System.in);

    String userInput = null;
    boolean quit = false;
    do {
        userInput = scanner.readLine();
        if(userInput != null && userInput.equals("quit")) {
            client.sendMessage(userInput);
        } else {
            quit = true;
        }
    } while(!quit);
}
当然,这是我刚刚编出来的,但这只是一个例子,一旦你的类结构得到了正确的分解,它们应该在哪里,就很容易连接到GUI

这个列表可以继续下去,但底线是你需要仔细看看什么类需要知道什么信息以及为什么。将类分开,将字段设置为私有,除非需要共享,否则不要共享信息!重要的是你真的要考虑减少


ServerClientFrontEnd.main
中,您有一个snipplet:

new ServerClientFrontEnd().startClient();

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        new ServerClientFrontEnd().setVisible(true);
    }
});
您正在创建两个
ServerClientFrontEnd
实例,一个启动客户端,另一个显示GUI。显示GUI的是更改字符串的
列表
,而另一个列表始终为空。要使其工作,请将snipplet更改为:

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        ServerClientFrontEnd fontEnd = new ServerClientFrontEnd();
        fontEnd.startClient();
        fontEnd.setVisible(true);
    }
});

嗯,不。创建一个(或者称为)并粘贴到这里。我不会在整个项目中寻找逻辑错误。我为我遇到问题的两个线程添加了一个代码块,并在出现问题的感兴趣区域之外添加了注释。我不认为我可以做一个SSCCE,因为它就是不工作,我不知道如何让它工作,即使我修剪了代码。“我不能让它工作”不是一个问题描述。你的代码真的很愚蠢。您有一个客户端和一个服务器,但它们都共享同一个GUI对象(ServerClientFrontEnd)。此外,您似乎正在从所有线程、客户端和服务器访问JFrame(同样是ServerClientFrontEnd)。那不行。