`
鬼大来晚了
  • 浏览: 66243 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA Runtime 调用第三方应用

    博客分类:
  • Java
 
阅读更多

有些时候我们需要在Java程序中调用一些exe程序或是脚本语言,例如.bat python 等。Java提供了Runtime对象及一些方法。
1、JAVA API:
首先,看一下Runtime的API:
Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.
有两个方法需要说一下:
(1)public static Runtime getRuntime()
Returns the runtime object associated with the current Java application. Most of the methods of class Runtime are instance methods and must be invoked with respect to the current runtime object.
这个函数用来返回当前java应用程序的Runtime对象,是一个静态函数。用户可以通过类直接调用(Runtime.getRuntime())。
(2)用来执行脚本的函数
public Process exec(String command)throws IOException
Executes the specified string command in a separate process with the specified environment and working directory.
该方法用来执行字符串形式的系统命令,返回一个管理子进程的Process对象
(3)Process对象:该对象有以下几个方法,用来操作子进程
abstract  void destroy()
          Kills the subprocess.
abstract  int exitValue()
          Returns the exit value for the subprocess.
abstract  InputStream getErrorStream()
          Gets the error stream of the subprocess.
abstract  InputStream getInputStream()
          Gets the input stream of the subprocess.
abstract  OutputStream getOutputStream()
          Gets the output stream of the subprocess.
abstract  int waitFor()
          causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.

2、使用方法:

Process p = null;
try {
	p = Runtime.getRuntime().exec("notepad.exe");
} catch (Exception e) {
	e.printStackTrace();
}
System.out.println("我想被打印...");

这样简单的运行第三方程序之后,会造成子进程还没有运行完,java程序就向下接着运行了。这对一些想等待第三方程序执行完的用户来说不合理,这里就要用到waitFor()方法。

在以上程序的.exec("")后,添加代码:
p.waitFor();
但是,这样会出现必须要等我们把记事本关闭打印语句才会被执行。并且你不碰手动关闭它那程序就一直不动,程序出现了挂起的现象。看一下这个函数的API:
Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
也就是说,等到当前的进程会等待子进程结束,如果子进程停止,该方法立即被返回。但是直接调用这个方法会导致当前线程阻塞,直到退出子进程。

产生阻塞的原因:因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入何从标准输入快速的读入都有可能造成子进程的所,甚至死锁。好了,问题的关键在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。接着来分析缓冲区,哪来的这个东西,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。

3、解决程序挂起,查了网上说的,基本都是开启两个线程,读取进程的输出和错误内容。
代码如下:


public class TestProcess {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		TestProcess test=new TestProcess();
		test.openNotepad();
	}


	public void openNotepad(){

		try {
			Process p = Runtime.getRuntime().exec("notepad.exe");
			  StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "Error");           
              StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), "Output");
              //开启两个线程读缓冲区内容
              errorGobbler.start();
              outputGobbler.start();
	    p.waitFor();
	    p.destroy();
		
		} catch (Exception e) {
				e.printStackTrace();
		}
	}

	class StreamGobbler extends Thread {
		 InputStream is;
		 String type;
		 StreamGobbler(InputStream is, String type) {
		  this.is = is;
		  this.type = type;
		 }

		 public void run() {
		  try {
		   InputStreamReader isr = new InputStreamReader(is);
		   BufferedReader br = new BufferedReader(isr);
		   String line = null;
		   while ((line = br.readLine()) != null) {
		    if (type.equals("Error"))
		         System.out.println(line);
		    else
		    	 System.out.println(line);
		   }
		  } catch (IOException ioe) {
		   ioe.printStackTrace();
		  }
		 }
		}


}


这个方法就解决了调用waitFor()方法阻塞无法返回的问题。






分享到:
评论

相关推荐

    Android代码-最简单的方法来询问Android的运行时权限

    Runtime Permission Simpliest way to ask runtime permissions on Android, choose your way : Kotlin Kotlin with Coroutines RxJava Java8 Java7 No need to override Activity or ...

    Java精华(免费版)

    而runtime exception则用来指示一种调用方本身无法处理或恢复的程序错误。   checked exception迫使你捕获它并处理这种异常情况。以java.net.URL类的构建器(constructor)为例,它的每一个构建器都会抛出...

    oracle如何使用java source调用外部程序

    Oracle调用第三方外部程序。Oracle使用sqluldr2快速导出大批量数据,然后用winrar压缩后发送邮件。 源码 java source create or replace and compile java source named jv_run_extpro as import java.io.*; ...

    Android异常 java.lang.IllegalStateException解决方法

    1. java.lang.IllegalStateException: No wrapped connection. 2.java.lang.IllegalStateException: Adapter is detached. 原因: 1.单线程一次执行一个请求可以正常执行,如果使用多线程,同时执行多个请求时就会...

    系统监控软件Sigar-System_Runtime.zip

    第二种,使用第三方的jar包进行获取,通过直接调用操作系统的api来获取系统相关数据。本文则主要介绍一种通过Hyperic-hq产品的基础包sigar.jar来实现服务器状态数据的获取。Sigar.jar包是通过本地方法来调用操作系统...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    在面向对象的程序设计中,这些行为用方 法实现。 在 OOP 技术中,对象充当了一个很重要的角色。对象的数据是组成对象的核心,而方法 则环绕这个核心并隐藏在对象之中。 2.2.2 封装 "封装"是 OOP 语言的优点之...

    Java编程经验

    这样希望大家不至于迷惑为什么总报错找不到类文件,不管是自己写的还是导入的第三方的jar文件(J2ee中经常需要导入的)。 3. 关于jdk和jre?? 大家肯定在安装JDK的时候会有选择是否安装单独的jre,一般都会一起安装...

    新版Android开发教程.rar

    � 由于采用了 Java 作为应用开发语言,目前可用的传统第三方应用还很少,但由于 Android 是一款完全 开 源的移动计算平台,相信第三方应用会很快的丰富起来。 � Google 提供了一套 Java 核心包 (J2SE 5,J2SE 6) 的...

    C#微软培训资料

    第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型...

    【05-面向对象(下)】

    •总之,第一步先找局部变量,第二步,内部类的属性,第三步。外部类的属性。 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/ 静态内部类 •如果用...

    操作系统(内存管理)

    void *malloc(long numbytes):该函数负责分配 numbytes 大小的内存,并返回指向第一个字节的指针。 void free(void *firstbyte):如果给定一个由先前的 malloc 返回的指针,那么该函数会将分配的空间归还给进程的...

Global site tag (gtag.js) - Google Analytics