How to run parallel python scripts from java using the ProcessBuilder - java

this is my first question here.
I am trying to run parallel python scripts (that is multiple instances of a same script) from java periodically using the ScheduledThreadPoolExecutor. What i tried to do was using the ProcessBuilder class. To test the concept i have put first script into infinite loop while the second writes something to file and exits. Python scripts i need to make should be identical to each other so i tried to run these two from multiple instaces of a same class that implements runnable.
However the second script never starts. I managed to solve this by creating many classes that have exactly same runnable. But it seems highly impractical to have 10-20 classes that are same. So can i do this somehow within one runnable?
Here is the code that shows how i tried to run scripts using the ProcessBuilder:
public class TestScripts{
public static void main(String[] args){
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(2);
threadPool.scheduleAtFixedRate(new MyTask1(), 1,2, TimeUnit.SECONDS);
threadPool.scheduleAtFixedRate(new MyTask1(), 1,2, TimeUnit.SECONDS);
}
}
class MyTask1 implements Runnable{
public void run(){
System.out.println("Task1 is running");
ProcessBuilder processBuilder = new ProcessBuilder("C:\\Python27\\python.exe",
"C:\\Python27\\test.py");
ProcessBuilder processBuilder2 = new ProcessBuilder("C:\\Python27\\python.exe",
"C:\\Python27\\test2.py");
processBuilder.redirectOutput(Redirect.INHERIT);
try {
Process process = processBuilder.start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Process process2 = processBuilder.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

There is a typo in the line starting 2nd process:
Process process2 = processBuilder.start();
should be of course:
Process process2 = processBuilder2.start();
Besides you are scheduling 2 tasks, where each task starts 2 processes. So each 2 seconds there are 4 processes started (2x test.py, 2x test2.py). If I understand correctly what you're trying to do, scheduling only one MyTask1 should be enough.

Related

Stopping a running java program gracefully

I'd been googling around for a way for me to send in command to a running Java program, but most of the post suggested to implement listener or wrap the program with a Jetty (or other server) implementation.
Is there a way to do this without adding additional dependencies?
The scenario is, i have a Java program which will be running indefinitely, and which will spawn a few running threads. I would like to be able to run a script to stop it, when it needs to be shut down, somewhat like the shutdown script servers tend to have. This will allow me to handle the shutdown process in the program. The program runs in a linux environment.
Thank you.
Implemented the shutdown hook and so far it looks good. The implementation codes:
final Thread mainThread = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
logger.info("Shut down detected. Setting isRunning to false.");
if(processors != null && !processors.isEmpty()){
for (Iterator<IProcessor> iterator = processors.iterator(); iterator.hasNext();) {
IProcessor iProcessor = (IProcessor) iterator.next();
iProcessor.setIsRunning(false);
try {
iProcessor.closeConnection();
} catch (SQLException e1) {
logger.error("Error closing connection",e1);
}
}
}
try {
mainThread.join();
} catch (InterruptedException e) {
logger.error("Error while joining mainthread to shutdown hook",e);
}
}
});
Thanks for the suggestion.

Need to execute a piece of code repeatedly for fixed duration in java

I have written a piece of code . How can I get that code to run for certain duration repeatedly, say for 10 second?
The ExecutorService seems to provide methods which execute tasks until they are either completed or else a timeout occurs (such as the invokeAll).
You can give a try to Quartz Job Scheduler
Quartz is a richly featured, open source job scheduling library that
can be integrated within virtually any Java application - from the
smallest stand-alone application to the largest e-commerce system.
Quartz can be used to create simple or complex schedules for executing
tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks
are defined as standard Java components that may execute virtually
anything you may program them to do. The Quartz Scheduler includes
many enterprise-class features, such as support for JTA transactions
and clustering.
If you are familiar with Cron in Linux , this will be a cakewalk for you .
Use a worker and start it in a thread, wait in the main thread for the specific time and stop the worker after this.
MyRunnable task = new MyRunnable();
Thread worker = new Thread(task);
// Start the thread, never call method run() direct
worker.start();
Thread.sleep(10*1000); //sleep 10s
if (worker.isAlive()) {
task.stopPlease(); //this method you have to implement
}
Not too sure why people downvoted the question. Be sure to in the future provide some sample code. Your answer however is simple here. Create a new thread to watch the wait. In simple code:
public class RunningClass {
public static void runThis(){
TimerThread tt = new TimerThread();
tt.timeToWait = 10000;
new Thread(tt).start();
while (!TimerThread.isTimeOver){
\\Code to execute for time period
}
}
class TimerThread implements Runnable {
int timeToWait = 0;
boolean isTimeOver = false;
#override
public void run(){
Thread.sleep(timeToWait);
}
}
The code above can be put in the same class file. Change the 10000 to whatever time you require it to run for.
You could use other options, but it would require you to have knowledge on workers and tasks.
not sure what was the exact requirement, but
if your req was to cancel only a long running task
you could use ExecutorService & Future (in jdk 5) as follows.
ExecutorService fxdThrdPl = Executors.newFixedThreadPool(2);
// actual task .. which just prints hi but after 100 mins
Callable<String> longRunningTask = new Callable<String>() {
#Override
public String call() throws Exception {
try{
TimeUnit.MINUTES.sleep(100); // long running task .......
}catch(InterruptedException ie){
System.out.println("Thread interrupted");
return "";
}
return "hii"; // result after the long running task
}
};
Future<String> taskResult = fxdThrdPl.submit(longRunningTask); // submitting the task
try {
String output = taskResult.get(***10**strong text**, TimeUnit.SECONDS***);
System.out.println(output);
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (TimeoutException e) {
***taskResult.cancel(true);***
}

Java Multithreading: How can i start external Java Programs, which are executing threads?

currently, i'm trying to write a programm, which should execute a seperate Java-program multiple times, but with different parameters. This executed Java-program calls a Thread-Class. Within this class, a connection to a (Game)Server is established. Once connected, the Threads sends a command to turn the connected player around every 10 milliseconds. I have 2 "solutions" for this:
The easy (working) one:
public class GeneralAgentTest {
public static void main(String [] args){
Thread thread = new Thread(new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15));
thread.start();
}
}
This is working correctly, but not actually my goal. I need to start several of this Threads (new Thread(new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15)); ) and each of this threads must be handled by a seperate process.
To do this, i wrote some code with an ProcessBuilder. This is within one class.
Second not correctly working one:
public void execute(Class class1, int a, String str, String team, String x,
String y) {
ProcessBuilder builder;
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator
+ "java";
String classpath = System.getProperty("java.class.path");
String className = class1.getCanonicalName();
builder = new ProcessBuilder(javaBin, "-cp", classpath,
className, ip, port, team, str, x, y);
try {
process[a] = builder.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("failed");
}
public void loadPlayers() {
process = new Process[4];
for (int i = 0; i < 4; i++) {
try {
execute(processes.StartProcesses.class, i,
playerCombo[i].getSelectedItem().toString(),
playerTeam[i].getText(), playerStartX[i].getText(),
playerStartY[i].getText());
} catch (Exception e) {
System.out.println("Failed to create processes for players");
e.printStackTrace();
}
}
}
These are the functions i wrote, to execute the class(es) who is/are starting the thread(s).
Following class is executed:
public class StartProcesses{
public static void main(String[] args) {
Thread t = null;
t = new Thread(new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15));
t.start();
JOptionPane.showMessageDialog(null, "should've started");
}
}
In my second try, the parameters which are given to the StartProcesses Class are containing some information like IP-Adresses, Portnumbers, Playerpositons and stuff like this. Anyway i was trying to execute the class with "hard" information, just to be sure it is working like in my first codepart.
The connections to the server are correctly established in both attempts, but in the first one the thread keeps working. In my second try it seems like the thread is dead after the connection is established. The process is still alive, since the connection to the server is still there.
This is a bit of code, but what i want to tell, is that the Thread is working correctly when executed manually, but it is not working correctly if i try to start the class automatically with the use of ProcessBuilders.
I really really hope you guys could understand what i am trying to say. Hopefully someone has a working solution for me.
Cheers.
EDIT: Add Code for HexagonRunner:
public class HexagonRunner extends GeneralAgent {
// Bunch of Methods
// Important Method:
#Override
protected void simulationCycle() {
turnAgent(40);
}
}
The simulationCycle() method, is the method that is going to be go through over and over again.
Since the class HexagonRunner is inherited from the class GeneralAgent, i'm going to post the relevant stuff of this class here as well:
public class GeneralAgent implements Runnable, UdpListener{
// Attributes, getters, setters, methods..
#Override
public final void run() {
// giving the worker threads the signal to start
mServerConnection.start();
mParser.start();
// waiting for the first information to be parsed, so that the
// simulation loop can run
try{
System.out.println("GeneralAgent-Run: waiting for latch");
mLogger.info("Run method: waiting for CountDownLatch");
mFirstDone.await();
}
catch(InterruptedException e){
System.out.println("GeneralAgent-Run: InterruptedException");
mLogger.info("Run method error: " + e.getMessage());
}
mLogger.info("Run method: CountDownLatch now 0, continue");
// setting the initial position
moveToPostion(mXStartCoord, mYStartCoord);
// the simulation loop
while (true){
simulationCycle();
// Shutdown if the game is over
if (mGameworld.getTime() >= 6000){ // later 6000+
System.out.println("Yeah, 50 runs completed -> Shutdown");
mLogger.info("General Agent - Time > 50, programm should terminate");
shutdown();
break;
}
// waiting for the threads to signal that they are
// ready (e.g. have new server information)
// for another round of the simulation loop
mPhaser.arriveAndAwaitAdvance();
}
}
I hope things get clearer now. I still have no idea where my code fails.
You could build somethin a lot simpler by using Executors. It' part of the comcurrent package introduced in Java 1.5. It basically works as follows:
// create a pool with 10 threads
ExecutorService executorService = Executors.newFixedThreadPool(10);
//loop as long as you need to detach your threads
for (int i = 0; i < 4; i++) {
// this actually contains the thread bit, will be executed in parallel
executorService.execute(new Runnable() {
public void run() {
// this is where your code is
new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15)
}
});
}
// clean up when you're done to prevent leaks
executorService.shutdown();
That's it, much simple and you don't need to spawn different JVMs through ProcessBuilder, which is a lot slower.

Check exit status of main

I am invoking the main class of a .class contained in the same folder from my Java code. That main is void, and I want to check whether it was successful or not by checking its exit status:
...
String[] arguments = new String[]{"a", "b"};
AnotherClass.main(arguments);
...
Any idea on how, being that AnotherClass.main(arguments); does not return anything?
Thank you.
Even better idea -- instead of trying to call a main method, instead create a method in your other class called testMain() which does the same thing as main except it returns the exit code instead of exiting.
System.exit() called in that main method will shut down your entire program. You want to run the other main in another thread and find the exit code for that thread.
Build the other program (name the jar AnotherClass.jar), add the jar to your path and try this:
int exitCode;
try {
Process process = Runtime.getRuntime().exec("java AnotherClass.jar",new String[]{"arg1","arg2"});
exitCode = process.waitFor();
System.out.println(exitCode);
} catch (IOException e) {
System.out.println("IO Error: " + e);
} catch (InterruptedException e) {
System.out.println("Inturrupted: " + e);
}
EDIT: The following will not work at all; System.exit() kills all threads.
This code will run another main method in a new thread, and when it exits it will not harm your current program.
Thread anotherProgram = new Thread(new Runnable() {
#Override
public void run() {
AnotherClass.main(new String[]{"foo","bar"});
}
});
anotherProgram.start();
If you mean the exit code parameter to System.exit(int status), you cannot access it, as when it is called by some part of the main method (or subsequently executed code), your application is exited, and so there is nothing left running to get at the code.
The only way to check the exit code of an application is using the OS, e.g. the $? environment variable in unix tells you the exit code of the last application to terminate in that session.
Edit: Here's an example using ProcessBuilder to do so:
Process p = new ProcessBuilder(System.getProperty("java.home")+"/bin/java", "fully.qualified.package.to.AnotherClass").start();
Integer exitCode = null;
while (exitCode == null) {
try {
exitCode = p.waitFor();
} catch (InterruptedException e) {
// handle e
}
}

using a timer to destroy/interupt a process in Java

Hi I am wondering how I could use a timer to destroy a process if it elapses a predefined time period in milisecs.
Currently I have a method which gets the thread from runtime
Runtime runtime = Runtime.getRuntime();
I then create separate process to execute a command using the runtime
Process process = runtime.exec(comman); //where command is a string with a defined command
I then handle the normal/error output streams before calling:
process.waitFor();
this waits for the process to terminate if it hasn't already.
My question is, how can I go about using a timer to terminate the process before it has finished, i.e. by calling:
process.destroy;
Basically, if the process works for more than a certain length of time, I want to destroy it prematurely.
I would then throw an InterruptedException if it was destroyed because of over runing.
I was told that using a timer would be the best way to achieve this, but wasnt sure if this was the case?
Any help would be hugely appreciated.
try
final Process p = ...
final Thread mainThread = Thread.currentThread();
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(1000);
p.destroy();
mainThread.interrupt();
} catch (InterruptedException e) {
}
};
};
p.waitFor();
if (mainThread.isInterrupted()) {
throw new InterruptedException();
}
t.interrupt();

Categories