4

In my program I do have a list of n items.

I will be iterating the list and initiate a process like this:

Runtime.getRuntime.exec("cmd /C start abc.bat"+listitem() )

I need to maintain a count of 4 processes. Once any one of the process is completed, I need to start the next process , so the process count should be 4.

I am able to initiate 4 process simultaneously, but not sure on how to keep the count of 4. Basically I need some notification once a process is terminated, so I can start the next, any threading is possible.

Any help on how to implement this, can somebody share a snippet on this above requirement?

Beryllium
  • 12,808
  • 10
  • 56
  • 86
Vigneshwaran
  • 475
  • 3
  • 8
  • 15

4 Answers4

12

Use an ThreadPoolExecutor of size 4 and a Runnable implementation which starts the Process and then invokes Process.waitFor(). Since the thread pool will be restricted to 4 threads and all 4 threads will start a process and then wait for it, you'll be certain there won't be more than 4 child processes running.

Some sample code to help you along your way:

ExecutorService executor = Executors.newFixedThreadPool(4);

executor.execute(new Runnable() {
    public void run() {
        //use ProcessBuilder here to make the process
        Process p = processBuilder.start();
        p.waitFor();
    }
});
Tim Bender
  • 20,112
  • 2
  • 49
  • 58
2
 public class ProcessRunner {

    public static void main(String[] args) throws IOException, InterruptedException {
        //Creating n threads as required
        ExecutorService exec = Executors.newFixedThreadPool(4);
        for(int i = 0; i < 4; i++){
            exec.execute(new ProcessRunnable());
        }

        Thread.sleep(10000);

        //whenever you want them to stop
        exec.shutdownNow();

    }   

}

class ProcessRunnable implements Runnable{
       @Override
       public void run(){
        do{
           Process p;
        try {
            p = Runtime.getRuntime().exec("cd ..");
            p.waitFor(); 
        } catch (IOException e) {
                    //Take appropriate steps
            e.printStackTrace();
        } catch (InterruptedException e) {
                    //Take appropriate steps
            e.printStackTrace();
        }

        }while(!Thread.interrupted());
       }
}

Process#waitFor()

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.

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • Thanks for the immediate Response .I tried this approach with a threadpool count of 4 , but the execution terminates after initiating and completion of 4 process . Threads are not called post the 4 process . Any suggestions – Vigneshwaran Aug 02 '13 at 08:01
  • @user2644818 I have edited the code to include the code that works for me. The 4 threads continuously run the process and as soon as it exits the thread runs it again in while loop until you call `shutdownNow()` – Narendra Pathai Aug 02 '13 at 10:03
1

You should have four threads that each take an assignment from a pool, then carry it out, then when it is done, carry out the next assignment. This would be how:

class Whatever extends Thread {
    public void run() {
        while (!interrupted()) {
            String str = listitem();
            if (str == null) // there are no more commands to run
                break;
            Runtime.getRuntime.exec(("cmd /C start abc.bat"+str).split("\\s")).waitFor();
}

Then start four of these threads.

tbodt
  • 16,609
  • 6
  • 58
  • 83
  • 1
    All this solution does is transform the problem from that of managing sub-process lifecycles to managing thread lifecycles. Take a cue from the other answerers and throw in an ExecutorService as I mentioned in my answer.. – Tim Bender Aug 02 '13 at 07:10
  • @TimBender His example is complete, it has a Runtime.getRuntime in it and I can just copy paste it completely in my code. Had you done the same, yours would have probably been the correct answer... – Radu May 16 '14 at 13:10
  • @Radu The purpose of SO is not necessarily to create copy/paste answers but instead good answers. My comment is still quite valid and this answer is low quality, but it is the OP's right to accept any answer they choose. – Tim Bender May 16 '14 at 20:19
  • @TimBender As you said, people have a right to choose. And I sir, choose not to cloud my head with all the stuff about stuff about stuff. – Radu May 17 '14 at 19:52
  • 2
    @Radu sure thing. http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread http://stackoverflow.com/questions/10723346/why-should-avoid-using-runtime-exec-in-java – Tim Bender May 18 '14 at 05:31
  • I have a little question, is this line Runtime.getRuntime.exec() working on main thread or background thread? Thanks! – Hilal Oct 28 '19 at 15:05
1

You can use fixed thread pool with size 4 which guarantees no more than 4 active threads at any given moment

    final ExecutorService ex = Executors.newFixedThreadPool(4);
    for(int i = 0; i < 100; i++) {
        ex.execute(new Runnable() {
            @Override
            public void run() {
              ... run the process here and wait for it to end
            }
        });
    }
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275