2013-09-30 34 views
0

我正在为一个研究项目构建一个配对的客户端/服务器应用程序。服务器端应用程序是一个具有主循环和ServerSocket对象的java二进制文件。当具有客户端应用程序的用户敲响服务器时,我实例化一个ClientSession类型的新对象,并为其发送通信的套接字。然后,我将它作为新线程运行,以便服务器应用程序的中心线程可以返回到等待呼叫。如何在Java中的线程之间传递进程ID?

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

到目前为止,这工作正常,但今天我遇到了一个新的挑战,即按照客户的要求运行perl脚本。该脚本基本上包装了一些对我的问题域非常有用的低级Unix操作系统函数。如果客户端请求启动此脚本的副本,我不能仅在ClientSession线程中启动它。 perl脚本需要在调用的生命周期后保留(可能需要几天或几周的时间才能在具有睡眠定时器的循环中运行)。

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

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

这会启动它,但现在它会死于ClientSession线程。

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

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

回答

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领域的包装。

+0

当我仔细看看这个任务时,似乎在任何给定的时间里都会有很多perl脚本的实例 - 在系统上每个注册用户最多有一个实例。 +1用于建议ProcessManager。建立其中一个将使生活变得更容易。 – Micah

2

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

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

当您的任务完成时,您可以将您想从任务中获取的信息传递给您的域特定可调用的构造函数,并在完成时将其恢复。

相关问题