Search on the blog

2015年9月12日土曜日

Javaから外部プロセスを起動する

Javaから外部プロセスを起動するサンプルを書いてみた。
  1. 外部プロセスを実行する
  2. 別スレッドで外部プロセスを実行する
の2つのサンプルを書いた。

外部プロセスを実行する
まずは簡単な例から。

以下のようなechoTwice.pyというプログラムを用意しておく。
#!/usr/bin/python

if __name__ == '__main__':
    x = raw_input()
    print x * 2

上記のプログラムをJavaから外部プロセスとして起動する。
以下のようにプロセスの標準入出力を使ってデータをやりとりすることも出来る。
package com.kenjih.sample;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class Sample1 {
	public static void main(String[] args) throws IOException {
		
		Scanner sc = new Scanner(System.in);
		String word = sc.nextLine();
		sc.close();
		
		new Sample1().run(word);
	}
	
	public void run(String word) throws IOException {
		ProcessBuilder processBuilder = new ProcessBuilder("./echoTwice.py");
		Process process = processBuilder.start();
		BufferedReader reader = 
				new BufferedReader(new InputStreamReader(process.getInputStream()));
		BufferedWriter writer = 
				new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
		
		writer.write(word);
		writer.newLine();
		writer.flush();
		
		String ret = reader.readLine();
		System.out.println(ret);		
	}
}

別スレッドで外部プロセスを起動する
次に別スレッドで外部プロセスを起動するサンプル。
別スレッドで呼び出すことで”制限時間付き”で外部プロセスを起動できる。
以下のようなechoWithDelayというプログラムを用意しておく。このプログラムは与えられた文字列をechoするだけだが、文字長に等しい秒数だけスリープする。
#!/usr/bin/python

import time

if __name__ == '__main__':
    x = raw_input()
    time.sleep(len(x))
    print x
このプログラムをJavaから別スレッドで起動する。
スレッドから処理結果を戻り値として受け取りたい場合は、Futureクラスを使うと便利。
5文字以上の文字列を渡すと処理時間オーバーとなり、例外がスローされる。
package com.kenjih.sample;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class Sample2 {
	
	class Task implements Callable<String> {
		
		private final String word;
		
		Task(String word) {
			this.word = word;
		}
		
		@Override
		public String call() throws Exception {
			
			ProcessBuilder processBuilder = new ProcessBuilder("./echoWithDelay.py");
			Process process = processBuilder.start();
			BufferedReader reader = 
					new BufferedReader(new InputStreamReader(process.getInputStream()));
			BufferedWriter writer = 
					new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));

			writer.write(this.word);
			writer.newLine();
			writer.flush();
			
			String ret = reader.readLine();
			return ret;
		}
		
	}
	
	public static void main(String[] args) throws IOException {

		Scanner sc = new Scanner(System.in);
		String word = sc.nextLine();
		sc.close();

		new Sample2().run(word);		
	}
	
	public void run(String word) {
		
		ExecutorService executor = Executors.newSingleThreadExecutor();		
		Future<String> future = executor.submit(new Task(word));
		
		try {
			System.out.println(future.get(5000, TimeUnit.MILLISECONDS));
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		} catch (TimeoutException e) {
			e.printStackTrace();
		} finally {
			executor.shutdown();			
		}
	}
}

0 件のコメント:

コメントを投稿