Ilja
Ilja

Reputation: 1215

limit maximum threads executing at time in java

Trying to figure out how threading in Java works, i just want to limit runnable threads executing by putting them all to array and then check in loop if some of them finished and pop them out, to have possibility to spawn a new thread, got exception in this code:

public class testThread implements Runnable {
public void run () {
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e){}
        System.out.println("This is the test thread");
    }   

    public static void main (String args[]) {
        int max_threads = 5;
        Thread worker;
        ArrayList<Thread> all_workers = new ArrayList<Thread>(max_threads   );
        for (int i =0; i<50; i++) {
            if (all_workers.size()<max_threads){
                worker = new Thread (new testThread());
                all_workers.add(worker);
                worker.start(); 
            } else{
                System.out.println("i ran all");
                while(all_workers.size()>=max_threads){
                    try{ 
                        System.out.println("Waiting for some to finish");
                        int counter = 0;
                        for (Thread wrk: all_workers){
                            if (!wrk.isAlive()){
                                all_workers.remove(counter);
                            }
                            counter ++ ;
                        }
                        Thread.sleep(500);
                    } catch (InterruptedException e){
                        System.out.println("Catched unhandled ");
                    }
                }
            }
        }

        for(Thread wrk: all_workers){
            try {
                wrk.join();
            } catch (InterruptedException e) {
            }
        }
    }
}

exception i got when i run it:

anybody@anymachine ~/java $ java testThread 
i ran all
Waiting for some to finish
Waiting for some to finish
This is the test thread
This is the test thread
This is the test thread
This is the test thread
This is the test thread
Waiting for some to finish
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
    at java.util.ArrayList$Itr.next(ArrayList.java:791)
    at testThread.main(testThread.java:39)

thank you for any help, if there is a good tutorial i would be much appriciated for link.

PS. if there is any debugger in java like pdb in python please let me know. thank you!

Upvotes: 2

Views: 7967

Answers (4)

Gray
Gray

Reputation: 116918

Exception in thread "main" java.util.ConcurrentModificationException

You are getting this because you are removing from an ArrayList while you are iterating across it. This is not allowed.

for (Thread wrk : all_workers) {
   if (!wrk.isAlive()) {
      // ERROR, you can't change the collection while you are in a for loop
      all_workers.remove(counter);
   }
   ...

If you need to remove from a list you are walking across, you should use the iterator.remove() instead:

Iterator<Thread> iterator = all_workers.iterator();
while (interator.hasNext()) {
    Thread wrk = interator.next();
    if (!wrk.isAlive()) {
        // this is allowed because you are using the iterator directly
        iterator.remove();
    }
}

A better solution to your specific situation is to use the ExecutorService code. What you do then is to create a fixed thread pool and submit your jobs to it:

// create a thread pool with 5 worker threads
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// define your jobs somehow
for (int i = 0; i < 50; i++) {
    threadPool.submit(new testThread());
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
// then wait for it to complete
threadPool.awaitTermination(Long.MAX_LONG, TimeUnit.MILLISECONDS);

Upvotes: 6

Thomas
Thomas

Reputation: 12029

You should have a look at the higher level threading utilities like ExecutorService and ThreadPools.

You should never terminate a thread manually and I suggest to avoid manual thread creation/management in general.

If you want to wait for a number of threads finishing, you may want to use a CountDownLatch. Here is an example.

Upvotes: 7

Alexei Kaigorodov
Alexei Kaigorodov

Reputation: 13535

First, why do you need to limit the number of running threads? Note, computer cannot simultaneously run more threads than it has processors anyway.

The main drawback of your solution is Thread.sleep(500). It causes unnecessary latency.

The right solution is to use a java.util.Executor with desired number of threads. Then you simply call executor.execute(new testThread()) instead of new Thread (new testThread()).start().

Upvotes: 1

Kanagavelu Sugumar
Kanagavelu Sugumar

Reputation: 19270

Change the below line

ArrayList<Thread> all_workers = new ArrayList<Thread>(max_threads);

To

Set<Thread> all_workers =  Collections.newSetFromMap(new ConcurrentHashMap<Thread,Boolean>())

Upvotes: 0

Related Questions