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中的多线程FTP服务器_Java_Multithreading - Fatal编程技术网

Java中的多线程FTP服务器

Java中的多线程FTP服务器,java,multithreading,Java,Multithreading,我正在用Java制作一个多线程FTP服务器,我有一个关于处理多个客户端的问题。现在,我有一个如下所示的服务器: public class Server { private static final int HOST_PORT = 6000; private ServerSocket serverSocket; public Server(ServerModel serverModel) throws IOException { serverSocket = new ServerSoc

我正在用Java制作一个多线程FTP服务器,我有一个关于处理多个客户端的问题。现在,我有一个如下所示的服务器:

public class Server {
private static final int HOST_PORT = 6000;

private ServerSocket serverSocket;

public Server(ServerModel serverModel) throws IOException {
    serverSocket = new ServerSocket(HOST_PORT);
}

public void start() {
    try {
        acceptClients();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void acceptClients() throws IOException {
    while (true) {
        Socket client = serverSocket.accept();
        ServerModel serverModel = new ServerModel();
        Thread worker = new Thread(new ServerWorker(client, serverModel));
        worker.start();
    }
}
}

以及一个ServerWorker对象,负责解释客户端命令并响应它们:

public class ServerWorker implements Runnable {

private ServerRemoteHandler serverRemoteHandler;
private ServerModel serverModel;

private static final int GET_CODE = 1;
private static final int PUSH_CODE = 2;
private static final int CHANGE_DIRECTORY_CODE = 3;
private static final int PRINT_WORKING_DIRECTORY_CODE = 4;
private static final int FILE_EXISTS_CODE = 5;
private static final int LIST_FILES_DIRECTORIES_CODE = 6;
private static final int EXIT_CODE = 0;

public ServerWorker(Socket client, ServerModel serverModel) throws IOException {
    this.serverModel = serverModel;

    try {
        serverRemoteHandler = new ServerRemoteHandler(client);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void parseCommand() {
    int command;

    try {
        while (true) {
            command = serverRemoteHandler.getCommand();
            switch (command) {
            case CHANGE_DIRECTORY_CODE:
                changeDirectory();
                break;
            case PRINT_WORKING_DIRECTORY_CODE:
                printWorkingDirectory();
                break;
            case FILE_EXISTS_CODE:
                fileExists();
                break;
            case LIST_FILES_DIRECTORIES_CODE:
                listFilesDirectories();
                break;
            case GET_CODE:
                pushFile();
                break;
            case PUSH_CODE:
                getFile();
                break;
            case EXIT_CODE:
                exit();
                break;
            }
        }
    } catch (IOException e) {
        exit();
    }
}

private void printWorkingDirectory() throws IOException {
    serverRemoteHandler.printWorkingDirectory(serverModel.getCurrentPath());
}

private void changeDirectory() throws IOException {
    String fileName = serverRemoteHandler.getFileName();
    boolean success = serverModel.changeDirectory(fileName);

    serverRemoteHandler.changeDirectory(success);
}

private void fileExists() throws IOException {
    String fileName = serverRemoteHandler.getFileName();
    serverRemoteHandler.fileExists(serverModel.fileExists(fileName));
}

private void pushFile() throws IOException {
    File file = serverModel.getFile(serverRemoteHandler.getFileName());
    long fileSize = serverModel.getFileSize(file);

    serverRemoteHandler.pushFile(file, fileSize);
}

private void listFilesDirectories() throws IOException {
    serverRemoteHandler.listFilesDirectories(serverModel.listFilesDirectories());
}

private void getFile() throws IOException {
    String fileName = serverRemoteHandler.getFileName();
    File file = new File(serverModel.getCurrentPath() + File.separator + fileName);

    serverRemoteHandler.getFile(file);
}

private void exit() {
    serverRemoteHandler.exit();
}

@Override
public void run() {
    while (true) {
        parseCommand();
    }
}
}

每个ServerWorker都有一个名为RemoteHandler的对象,其任务是从流发送和接收信息。我的问题是关于这一行:

Thread worker = new Thread(new ServerWorker(client, serverModel));

这个线安全吗?这是一种很好的实施方式吗?谢谢。

是的,它是线程安全的。该行中的所有内容都是方法本地的,因此它只能由当前线程访问,然后工作线程启动,而这个线程循环并获取这些变量的一组新值


(当然,这并不意味着整个程序都是线程安全的。)

太好了,非常感谢。我还有一个问题。既然每个线程都获得了一个新的可运行对象,那么由于没有共享变量,它本身就不是线程安全的吗?@namarino41这是正确的。避免共享变量,避免线程安全问题。这当然包括
静态
变量。这就是我的想法。非常感谢您的帮助,非常感谢。同意,方法本地将在堆栈中,只要serverSocket类(不是方法本地)之间不共享任何内容。祝你好运:)@amitmah方法局部变量在堆栈上,句号。其余的都与此无关。这个问题已经回答了。你只是在制造混乱。你真的需要
ServerWorker、ServerModel、
ServerRemoteHandler
三者吗?对我来说似乎有点过分了。该模型实际上只是一个返回文件信息的实用程序类。远程处理程序将所有网络交互抽象出来,服务器工作者实现runnable。你建议用不同的方式做吗?不建议。我可能会做得更简单一些,但你说的话听起来很合理。我知道这不是为了讨论,只是出于好奇,你会怎么做?总是想知道如何更好地设计这些东西。只要快速浏览上面的内容,我可能根本没有
ServerRemoteHandler
,而且我肯定会将所有文件系统的东西,如
changeDirectory()
放入
ServerModel
,我可能会将其重命名为远程文件系统客户端视图。但我从来都不是MVC的粉丝。