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

问题描述:

我创建了一个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; 
} 

Thread上的run()方法实际上并未启动新线程,请尝试使用Thread.start()代替。

+1

哇。那非常骨头。但你是对的。那样做了。非常感谢Mike! – Rodney 2011-05-09 21:17:19

+1

我不止一次为此而堕落。 :-) – 2011-05-10 05:23:38

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

run()方法被误导地命名。因为Thread实现Runnable接口run()方法是公开的,但它是而不是当您想要启动新线程时调用正确的方法。调用run()会导致线程代码在当前的线程中运行。

必须调用start()导致被实例化一个新的线程:

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

谢谢约翰。那样做了。我感谢你抽出时间。 – Rodney 2011-05-09 21:20:15