当前位置: 首页 > 面试题库 >

Java-线程,Swing和ServerSocket

龚振
2023-03-14
问题内容

我知道我知道,到处已经有上百万个问题和答案。关于它的大量真正详尽的文章,几种示例。我已经花了几个小时阅读有关它的信息,但这并不能解决问题。我之所以这样问,是因为我仍然不安静地理解我需要做的事情,显然是因为我的代码仍然无法正常工作。我想到了Swing如何与EDT一起工作,并且如果要使用ServerSocket的accept()方法,我将需要为Swing启动一个新线程(我认为?)。当我按原样运行代码时,窗口将打开并冻结。
我的问题是有人可以看看我的代码,告诉我我做错了什么,然后像我只有半个头脑一样向我解释吗? __(因为这就是我的感觉。:P)

主类

package com.sever.core;

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

import javax.swing.SwingUtilities;

public class Main {

private SocketManager network;
public static void main(String[] args){

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Window window = new Window();
            window.setVisible(true);
        }       
    });

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Main main = new Main();
            main.run();
        }       
    });


}

public void run(){
    network = new SocketManager(25595);

    while(true){
        try {
            network.setSocket(network.getServerSocket().accept());
            AddUser(network.getSocket());
            Thread x = new Thread(network);
            x.start();
        } catch (Exception e) {
            System.out.println("Failed to connect.");
        }
    }

}

public void AddUser(Socket s){
    try {
        Scanner input = new Scanner(s.getInputStream());
        network.addUser(input.nextLine());
    } catch (Exception e) {

    }
}
}

Window.class

package com.sever.core;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.*;

public class Window extends JFrame{

private int screenWidth = 800;
private int screenHeight = 600;
private Thread thread;

private JPanel window = new JPanel();
private JTextArea consle = new JTextArea("Server started....");
private JTextField input = new JTextField();
private JScrollPane consleinput = new JScrollPane(consle);

public Window(){
    this.setName("NAMEHERE - Server Software");
    setResizable(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(screenWidth,screenHeight);  
    window.setBackground(Color.DARK_GRAY);
    window.setLayout(new BoxLayout(window, BoxLayout.Y_AXIS));

    consleSetup();
    addComponets();
}

private void addComponets(){
    add(window);
    window.add(consleinput);
    window.add(input);
}

private void consleSetup(){
    consle.setEditable(false);
    consle.setLineWrap(true);
    consle.setBorder(BorderFactory.createEmptyBorder(3,3,3,3)); 
    consleinput.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    input.setMaximumSize(new             Dimension(Integer.MAX_VALUE,input.getPreferredSize().height));
}

private void addListeners(){
    input.addActionListener(new ActLis());
    input.setActionCommand("input");
}

}

SocketManager.class

package com.sever.core;

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class SocketManager implements Runnable{

private Socket sock;
private ServerSocket sersoc;
private PrintWriter output;
private BufferedReader input;
private Thread thread;

public ArrayList<Socket> currentConnections = new ArrayList<Socket>();
public ArrayList<String> currentUsers = new ArrayList<String>();


public SocketManager(String ip, int port){
    try{
        sock = new Socket(ip,port);
        PrintWriter output = new PrintWriter(sock.getOutputStream());
        BufferedReader input = new BufferedReader(
                new InputStreamReader(sock.getInputStream()));
        System.out.println("Server: socket started.");
    }catch(Exception e){
        System.out.println("Server: Socket failed to connect.\n");
    }
}

public SocketManager(int port){
    try {
        sersoc = new ServerSocket(port);

    } catch (IOException e) {
        System.out.println("Server: Socket failed to connect.\n");
    }
}

public SocketManager(Socket socket){
    this.sock = socket;

    try{
        output = new PrintWriter(sock.getOutputStream());
        input = new BufferedReader(
                new InputStreamReader(sock.getInputStream()));
    }catch(Exception e){

    }
}

public synchronized void checkConnetion(){
    if(!sock.isConnected()){
        for(int x = 0; x <= currentConnections.size(); x++){
            if(currentConnections.get(x) == sock){
                currentConnections.remove(x);
                System.out.println("Server: Disconnecting from: " + currentConnections.get(x) + "\n");
            }
        }
    }
}

public synchronized Socket getSocket(){
    return sock;
}

public synchronized ServerSocket getServerSocket(){
    return sersoc;
}

public synchronized void setSocket(Socket s){
    System.out.println("Setting socket to: " + s.getInetAddress());
    sock = s;
}

public synchronized void addSocket(Socket s){
    currentConnections.add(s);
}

public synchronized void addUser(String u){
    currentUsers.add(u);
}

public synchronized ArrayList<Socket> getConnections(){
    return currentConnections;
}

public synchronized ArrayList<String> getUsers(){
    return currentUsers;
}

public synchronized void send(String data){
    try{
        output.println(data);
    }catch(Exception e){

    }
}

public synchronized void close(){
    try{
        sock.close();
    }catch(Exception e){

    }
    output = null;
    input = null;
    System.gc();
}

public synchronized boolean isConnected(){
    return (sock == null) ? false : (sock.isConnected() && !sock.isClosed());
}

@Override
public void run() {
    System.out.println("Is runing.");
    while(true){
        try {
            checkConnetion();
            if(input.readLine().isEmpty()){ 
                return;
            }

            output.println("Server: Recived your message.");
        } catch (Exception e) {

        } finally{
            try {
                sock.close();
            } catch (Exception e) {

            }
        }
    }

}

}

ActLis类

package com.sever.core;

import java.awt.event.*;
import javax.swing.*;

public class ActLis implements ActionListener{

private JTextField actionField;
public ActLis(){

}

public ActLis(JTextField t){
    actionField = t;
}

@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    String cmd = e.getActionCommand();

    if(cmd == "input"){

    }
}

}

-编辑— SwingWorker的新Main.class

package com.sever.core;

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Main {

private SocketManager network;
public static void main(String[] args){

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Window window = new Window();
            window.setVisible(true);
        }       
    });

    SwingWorker server = new SwingWorker(){
        @Override
        protected Object doInBackground() throws Exception {
            Main main = new Main();
            main.run();
            return null;
        }

    };
    server.run();

}

public void run(){
    network = new SocketManager(25595);

    while(true){
        try {
            network.setSocket(network.getServerSocket().accept());
            AddUser(network.getSocket());
            Thread x = new Thread(network);
            x.start();
        } catch (Exception e) {
            System.out.println("Failed to connect.");
        }
    }

}

public void AddUser(Socket s){
    try {
        Scanner input = new Scanner(s.getInputStream());
        network.addUser(input.nextLine());
    } catch (Exception e) {

    }
}
}

问题答案:

您正在从EDT的Socket中读取内容。这意味着您将其阻止。调用invokeLater仅会使您的Runnable在EDT上执行。您在EDT上打了两个电话,其中一个是您的套接字。

考虑在SwingWorker中移动套接字,该套接字将Socker的值逐步返回到GUI。



 类似资料:
  • 问题内容: 想不通这一点。使用worker或invokeLater,UI仍然冻结。下载每个文件后,我希望更新JList。但是JList仅在踩踏返回后才更新。 这是代码: 任何示例都会有所帮助。 问题答案: 下载在后台线程文件,只是包装的。 会更可靠。 附录:作为@mre笔记,也可以很容易地报告中期业绩,如图所示这里。

  • 我想举例说明一个关于铁路的项目。 我决定使用Swing。我在JPanel中有一个背景图,我画了在铁路上移动的小圆圈。如果我只有一列火车,它会非常完美,但是我想增加更多的火车。 这是我开始做的(和工作): “go”读取一个数组列表,其中包含我的圆应该指向的坐标。 我真的不知道如何创造几列火车。我应该创建几个JPanel还是只创建一个包含所有圆圈的JPanel? 如果我记得很清楚,我应该使用线程,但我

  • Java Swing教程使用SwingUtilities。invokeLater创建GUI(如这里所示)。这里解释了为什么要这样做——大多数Swing对象都不是线程安全的。另一方面,我所看到的大多数JRubySwing示例只是设置了脚本中可见的顶部框架(如这里所示——归档中的“gui”目录)。 问题是,在 JRuby 脚本中创建应用程序顶部帧时,我是否应该遵循使用 SwingUtilities.i

  • 我使用以下代码,每0.5秒用相同的句子,但用另一个点替换一个JLabel。 这是使用线程的真正目的吗?这会影响程序的速度吗?如果我正在做的事情是如此愚蠢,有没有其他方法可以做这样愚蠢的事情?

  • 问题内容: 我正在尝试用Java绘制曲线。一个简单的以(X,Y)开始,(X,Y)结束和曲线量的贝塞尔曲线就足够了。 我找不到在Swing中执行此操作的方法。如果不在Swing中,我可以使用一些简单的数学方法吗?我将如何在Swing中实现它? 编辑:我知道如何通过重写paint(Graphics g)方法绘制形状和线条。 问题答案: 您可以使用Java 2D Object Path2D.Double

  • 问题内容: 我在维护的Swing应用程序中遇到了僵局,尽管我有一个可行的解决方法,但我不确定我是否了解自己在做什么,还没有隐藏可能弹出的竞争条件稍后再试。 线程跟踪显示死锁发生在两个线程AWT-EventQueue-0和AWT- EventQueue-1之间。我的第一个问题是,如果其中一个是臭名昭著的事件调度线程。这两个线程在堆栈跟踪的底部都有以下内容: 我认为问题的根源在于应用程序类将域数据与图