0

我正在为一个研究项目构建一个配对的客户端/服务器应用程序。服务器端应用程序是具有主循环和 ServerSocket 对象的 java 二进制文件。当具有客户端应用程序的用户响起服务器时,我实例化了一个类型为 ClientSession 的新对象,并为它提供将发生通信的套接字。然后我将它作为一个新线程运行,以便服务器应用程序的中心线程可以返回等待调用。

然后,每个 ClientSession 线程都会根据来自客户端程序的请求进行一些处理。它可能接受一个字符串并返回一个小的 SQLite .db 文件作为响应,或者接受一个不同的字符串并返回一个包含文件和文件大小列表的 Java 序列化对象。在所有情况下,ClientSession 线程都是短暂的,并在套接字关闭时关闭。

到目前为止,这一切正常,但今天我面临一个新的挑战,即根据客户的要求运行一个 perl 脚本。该脚本基本上包含了一些对我的问题域有用的低级 Unix OS 函数。如果客户端请求启动此脚本的副本,我不能只在 ClientSession 线程中启动它。perl 脚本需要在调用生命周期后持续存在(可能在带有睡眠计时器的循环中运行数天或数周)。

我想做的是在我的服务器应用程序上设置一个单独的线程并让它包装这个 perl 脚本。

    Runtime.getRuntime.exec('perl script.pl'); 

这将启动它,但现在它会随着 ClientSession 线程而死。

我的想法类似于声明一个 PerlThread 对象,要求它知道谁在请求新线程的用户 ID 作为其构造函数的一部分,让它实现 Runnable 接口,然后只需在新实例上执行 thread.start()它。但在我到达那里之前,我必须在子线程和服务器应用程序的主线程之间进行一些消息传递。所以这个设置让我想到了我的问题:

如何从子线程将消息传递回我的主服务器程序并告诉它客户端请求启动 perl 包装线程?

4

2 回答 2

2

您应该查看ExecutorService以获得在单独线程上运行作业的更好技术。它比 Thread.start() 或 Runnable.run() 更强大、更方便。

您可以查看Callable构造以了解如何从在其他线程上运行的作业中获取结果。

您可以将要在任务完成时从任务中获取的信息传递到特定于域的可调用的构造函数中,当它完成时,您可以将其取回。

于 2013-09-30T17:24:29.233 回答
1

如何从子线程将消息传递回我的主服务器程序并告诉它客户端请求启动 perl 包装线程?

我会在某个地方存储一个对象,该对象包含该对象UserId以及关联的Process对象。static volatile如果只有其中一个,您可以将其存储在一个字段中。就像是:

public class ClientHandler {
    ...
    private static volatile UserProcess userProcess;
    ...
    // client handler
    if (userProcess != null) {
        // return error that the perl process is already started
    } else {
        // start the process
        Process process = Runtime.getRuntime.exec('perl script.pl');
        userProcess = new UserProcess(userId, process);
    }

然后主程序可以通过查看是否有任何客户端运行了 perl 脚本ClientHandler.userProcess

如果您可以在客户端上运行多个进程,那么我将ProcessManager围绕这些UserProcess对象的集合包装某种类。像startProcess(...), listProcesses(), ... 然后主类会询问ProcessManager正在运行哪些进程或哪些用户启动了哪些进程等。

该类UserProcess只是UserIdProcess字段的包装。

于 2013-09-30T17:24:14.580 回答