运行外部进程的非阻塞线程

时间:2011-05-09 20:39:28

标签: java multithreading nonblocking

我创建了一个Java GUI应用程序,它充当许多低级外部进程的包装器。该实用程序按原样工作,但迫切需要一个重大改进。

我希望我的外部进程以非阻塞方式运行,这样我就可以并行处理其他请求。简而言之,我希望能够在生成数据时处理来自外部流程的数据。但似乎我检查并查看外部进程是否仍在运行的基本尝试是阻塞。

以下是我的ExternalProcess类的摘录。有关线程和阻塞的特定Java功能问题,请参阅内联注释。

public void Execute()
{
    System.out.println("Starting thread ...\n");
    Runner = new Thread(this, "ExternalProcessTest");
    Runner.run();
    System.out.println("Ending thread ...\n");
}

public void run() 
{
    System.out.println("In run method ...\n");  // Debug purposes only. 
        // Show that we are in the run loop.
    try
    {
        // Execute string command SomeCommand as background process ...
        Process = Runtime.getRuntime().exec(SomeCommand);
        while(IsRunning())
        {
            // External process generates file IO.  I want to process these
            // files inside this loop.  For the purpose of this demo I have
            // removed all file processing to eliminate it as the cause
            // of blocking.  THIS ROUTINE STILL BLOCKS!
            Thread.sleep(1000);
        }
    }
    catch(Exception e)
    {
        System.out.println(e);
    }
    System.out.println("Exiting run method ...\n");  // Debug purposes only.
        // Show that we are exiting the run loop.
}

// Process (instantiated from Runtime.getRuntime().execute doesn't supports
// either fire-and-forget backgrounding (non-blocking) or you can wait for 
// the process to finish using the waitFor() method (blocking).  I want to
// be able to execute a non-blocking external process that I monitor via
// threading allowing me to process the external process file IO as it is
// created.  To facilitate this goal, I have created an isRunning() method
// that uses the exitValue() method.  If the process is still running, a 
// call to exitValue() will throw an IllegalThreadStateException exception.
// So I simply catch this execption to test if the background process is
// finished -- at which point I can stop processing file IO from the 
// process.  Is this the source of the blocking?  If so, is there another
// way to do this?
public boolean IsRunning()
{
    boolean isRunning = false;
    try
    {
        int exitVal = Process.exitValue();
    }
    catch(IllegalThreadStateException e)
    {
        isRunning = true;
    }
    return isRunning;
}

2 个答案:

答案 0 :(得分:9)

Thread上的run()方法实际上并没有启动新线程,而是尝试使用Thread.start()。

答案 1 :(得分:7)

Runner = new Thread(this, "ExternalProcessTest");
Runner.run();

run()方法被欺骗性地命名。由于Thread实现了Runnable接口,因此run()方法是公开公开的,但是当您想要启动新线程时,是正确的方法。调用run()会导致线程代码在当前线程中运行。

您必须调用start()才能实例化新线程:

Runner = new Thread(this, "ExternalProcessTest");
Runner.start();