对象输出流不与mulithreading一起使用

时间:2016-08-23 04:43:59

标签: java multithreading sockets server objectoutputstream

我正在为在服务器和客户端系统上运行的游戏创建聊天,当然还有服务器客户端系统上的游戏,但是我无法让我的多线程程序工作,我将在下面解释如何。我可以说服务器客户端系统在单线程时工作。

首先,我的连接类使用以下方法:

public void sendObjects(Object obj) throws IOException{
        output.writeObject(obj);
        output.flush();

}   
public Object receiveObjects() throws IOException, ClassNotFoundException{
        return input.readObject();
}

我正在运行的所有类是Frame类:

public class Frame implements ActionListener{

private int width;
private int height;
private JFrame jframe;
private Board board;
private JTextArea textBox;
private JScrollPane pane;
private Connection connection;
private JTextArea userText;
private JScrollPane userPane;
private JButton send;
private NetworkReceiver net;


public Frame(int width, int height, Connection connection, Board player, Board opponent){
    this.width = width;
    this.height = height;
    this.connection = connection;

    board = new Board(player, opponent);
    init();
    textBox = new JTextArea("CHAT WINDOW");
    textBox.setWrapStyleWord(true);
    textBox.setLineWrap(true);
    textBox.setBackground(Color.GRAY);
    textBox.setBounds(height, 0, width - (height) - 20, height-40);
    textBox.setEditable(false);

    userText = new JTextArea("Enter Messages Here");
    userText.setWrapStyleWord(true);
    userText.setLineWrap(true);
    userText.setBackground(Color.WHITE);
    userText.setBounds(height, height-40, width - (height) - 20, 40);

    pane = new JScrollPane(textBox, 
            ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    pane.setBounds(height, 0, width - (height), height-40);

    userPane = new JScrollPane(userText, 
            ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    userPane.setBounds(height, height-40, width - (height) - 20, 40);

    send = new JButton();
    send.setIcon(Utility.getImageIcon(Utility.getBufferedImage(Assets.send)));
    send.setBounds(width - 20, height - 40, 20, 40);
    send.addActionListener(this);
    send.setBackground(Color.WHITE);


    jframe = new JFrame();
    jframe.setBackground(Color.DARK_GRAY);
    jframe.getContentPane().setPreferredSize(new Dimension(width, height));
    jframe.setLayout(null);
    jframe.pack();

    jframe.setLocationRelativeTo(null);
    jframe.add(pane);
    jframe.add(userPane);
    jframe.add(send);

    for(Space[] s: board.getSpaces()){
        for(Space space: s){
            jframe.add(space);
        }
    }
    for(Space[] s: board.getSpaces()){
        for(Space space: s){
            space.addActionListener(this);
        }
    }

    for(Space[] s: board.getSpaces()){
        for(Space space: s){
            if(space.getTile() != null){
                space.setBackground(space.getTile().getColor());
            }
        }
    }
    for(Space[] s: board.getSpaces()){
        for(Space space: s){
            if(space.getPiece() != null){
                space.setIcon(Utility.getImageIcon(space.getPiece().getImage()));
            }
        }
    }

    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jframe.setVisible(true);

    net = new NetworkReceiver(connection, this);
    net.start();
}

private void init(){        
  //stuff
}

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == send){
        send();
    }

}

private synchronized void send() {
    String message = "YOU- " + userText.getText();
    userText.setText("");
    String totalMessage = textBox.getText();
    textBox.setText(totalMessage + "\n" + message);
    new NetworkSender(connection, message).start();
}

public synchronized void showMessage(String s){
    String totalMessage = "Opponent- " + textBox.getText();
    textBox.setText(totalMessage + "\n" + s);
}

我不想在上面的构造函数中删除任何更多内容,以防它以某种方式导致问题(我怀疑但因为我找不到比安慰更安全的问题)

以下是NetworkSender和NetworkReceiver类:

public class NetworkSender extends Thread{

private Connection c;
private String msg;

public NetworkSender(Connection c, String msg){
    this.c = c;
    this.msg = msg;
}

public synchronized void run(){
    try {
        System.out.println("Trying to send");
        c.sendObjects(msg);
        System.out.println("Sent");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

public class NetworkReceiver extends Thread{

private Connection c;
private boolean running = true;
private Frame f;

public NetworkReceiver(Connection c, Frame f){
    this.c = c;
    this.f = f;
}

public synchronized void run(){
    while(running){
        System.out.println("running");
        Object obj = null;
        try {
            obj = c.receiveObjects();
            System.out.println("received");
        } catch (ClassNotFoundException e) {
            System.out.println("failed - class exception");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("failed - IO exception");
            e.printStackTrace();
            running = false;
        }
        if(obj != null){
            if(obj instanceof String){
                f.showMessage((String)obj);
            }
        }
    }
}

public void kill(){
    running = false;
}

}

破解的确切位置在NetworkSender类中。在控制台中,我收到“尝试发送”但从未“发送”。这让我认为我设置的线程错误,线程无法相互通信(发送方和接收方线程),或者服务器/客户端系统不正确地进行多线程。

我已经广泛地查找了这个问题,但是我无法在任何有效的地方找到解决方案,所以如果我有一个解决方案,我会道歉。如果一切都在检查,我可以发布我的连接,服务器和客户端类,如果需要,但我认为他们的功能,因为他们在EDT工作。当我在网上搜索近4个小时时,我会问你,如果你认为这是一个重复的问题,你首先评论一个链接,因为我几乎可以肯定我已经看到它已经大声笑了。

0 个答案:

没有答案