Micah
Micah

Reputation: 514

How to get pass a process ID between threads in Java?

I'm building a paired client/server application for a research project. The server-side application is a java binary that has a main loop and a ServerSocket object. When a user with the client-side application rings up the server, I instantiate a new object of type ClientSession, and give it the socket over which communications will occur. Then I run it as a new thread so that the central thread of the server application can go back to waiting for calls.

Each ClientSession thread then does some processing based on requests from the client program. It might accept a string and throw back a small SQLite .db file in response, or accept a different string and send back a Java serialized object containing a list of files and file sizes. In all cases the ClientSession thread is shortlived, and closes when then socket is closed.

And so far this is working fine, but today I have a new challenge to run, of all things, a perl script as per a client's request. The script basically wraps some low-level Unix OS functions that are useful to my problem domain. If a client makes a request to start up a copy of this script, I can't just launch it in the ClientSession thread. The perl script needs to persist after the lifetime of a call (perhaps for days or weeks running in a loop with a sleep timer).

What I'd like to do is set up a separate thread on my server application and have it wrap this perl script.

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

This will start it up, but right now it'll die with the ClientSession thread.

My thought would be something like declare a PerlThread object, require it to know the UserID of who's requesting the new thread as part of its constructor, have it implement the Runnable interface, then just do a thread.start() on a new instance of it. But before I can get there, I have to do some message passing between a child thread and the main thread of my server application. So that setup brings me to my question:

How do I pass a message back to my main server program from a child thread and tell it that a Client requested a perl wrapper thread to start?

Upvotes: 0

Views: 349

Answers (2)

Gray
Gray

Reputation: 116878

How do I pass a message back to my main server program from a child thread and tell it that a Client requested a perl wrapper thread to start?

I would store an object somewhere that wraps the UserId as well as the associated Process object. You could store it in a static volatile field if there is just one of them. Something like:

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);
    }

Then the main program can find out if any clients have the perl script running by looking at ClientHandler.userProcess.

If you can have multiple processes running on the client then I'd wrap some sort of ProcessManager class around a collect of these UserProcess objects. Something like startProcess(...), listProcesses(), ... Then the main class would ask the ProcessManager what processes are running or what users started what processes, etc..

The UserProcess class is just a wrapper around the UserId and Process fields.

Upvotes: 1

codethulhu
codethulhu

Reputation: 3996

You should look at ExecutorService for a better technique for running jobs on separate threads. It's much more powerful and convenient than Thread.start() or Runnable.run().

You can look at the Callable construct to see how to get results back from jobs which run on other threads.

You could pass the information you want to get back from the task when it completes into the constructor for your domain specific callable, and when it completes, you can get it back.

Upvotes: 2

Related Questions