g00glechr0me
g00glechr0me

Reputation: 365

How can I tell other threads in threadpool to stop after one thread completes the task?

Here is my code:

class Processor implements Runnable {

    private int id;
    private Integer interaction;
    private Set<Integer> subset;
    Iterator<Integer> iterator;
    ArrayList<Integer> par;

    public Processor(int id, Integer interaction, Set<Integer> subset, Iterator<Integer> iterator, ArrayList<Integer> par) {
        this.id = id;
        this.interaction = interaction;
        this.subset = subset;
        this.par = par;
        this.iterator = iterator;
    }

    public void run() {
        System.out.println("Starting: " + this.id);
        if (this.par.contains(this.interaction)) {
            this.subset.add(this.interaction);
            increaseScore(this.subset);
            if (!this.subset.contains(this.interaction)) {
                //TELL ALL OTHER THREADS TO STOP WHILE THIS THREAD REMOVES THE VALUE FROM THE ITERATOR
                iterator.remove();
            }
        }

        System.out.println("Completed: " + this.id);

    }
}

public class ConcurrentApp {

    public static void main(String[] args) {

        ExecutorService executor = Executors.newFixedThreadPool(4);
        ArrayList<Integer> par1 = new ArrayList < Integer > ();
        long start = System.nanoTime();

        int i = 1;
        while ((par1.size() > i)) {
            for (Iterator<Integer> iterator = par1.iterator(); iterator.hasNext();) {
                Integer interaction = iterator.next();
                ArrayList<Integer> removed = new ArrayList<Integer> (par1);
                removed.remove(interaction);
                ArrayList<Set<Integer>> subsets = getSubsets(removed, i);
                for (int j = 0; j < subsets.size(); j++) {
                    executor.submit(new Processor(j, interaction, subsets.get(j), iterator, par1));
                }
                executor.shutdown();
                System.out.println("All tasks submitted");
                try {
                    executor.awaitTermination(1, TimeUnit.DAYS);
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("All tasks completed");
            i++;
        }
        long end = System.nanoTime();

        System.out.println("Program Completed in: " + (end - start) * 0.000000001);

    }
}

My code flow is as follows:

  1. Start with an ArrayList of Integers called par and iterate through each element (we'll call A) in this collection

  2. Remove A from par to obtain B

  3. Find all subsets of size i (in the range 1 to par.size())

  4. [Multithreaded] For each subset of size i, add back in A to obtain a new collection C. Then find the value that when deleted increases the score of C the most. [Condition]If that value is A, delete A from par and move on to the next element in par. If A is not deleted for any of the subsets of size i, continue to the next element in par.

My intention is for each thread to work with one of the subsets and perform the Multithreaded step above until one of the threads meets the Condition. I think I implemented this correctly but would appreciate a second set of eyes since I'm new to concurrent programming.

Question 1: In the multithreaded step above, how can I tell all the other working threads from the threadpool to stop their task and go back into the threadpool once a single thread meets the Condition?

Questions 2: Is there a way for me to have multiple threads simultaneously work on different sets of different sized subsets (so multiple values of i at once) AND have multiple threads perform the Multithreading step above for a given set of subsets (which is what I've already done)? Essentially this is like breaking my entire job into two tasks: Task 1 is to look at the sets of subsets of size 1, 2, 3...par.size() and Task 2 is to look at each element in the set of subsets.

Appreciate the help!

Upvotes: 2

Views: 281

Answers (2)

Ravindra babu
Ravindra babu

Reputation: 38910

Question 1: In the multithreaded step above, how can I tell all the other working threads from the threadpool to stop their task and go back into the threadpool once a single thread meets the Condition?

Use invokeAny API of ExecutorService

<T> T invokeAny(Collection<? extends Callable<T>> tasks,
                long timeout,
                TimeUnit unit)
         throws InterruptedException,
                ExecutionException,
                TimeoutException

Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses. Upon normal or exceptional return, tasks that have not completed are cancelled. The results of this method are undefined if the given collection is modified while this operation is in progress.

Questions 2: Is there a way for me to have multiple threads simultaneously work on different sets of different sized subsets (so multiple values of i at once) AND have multiple threads perform the Multithreading step above for a given set of subsets (which is what I've already done)?

You can do it with . If you face any issues in implementing above, share your issues. Even if you want to wait for completion of all tasks, you can use invokeAll. If you want to improve the performance, you can use ForkJoinPool

Upvotes: 0

ControlAltDel
ControlAltDel

Reputation: 35011

Q1: Use a volatile static variable (maybe a volatile AtomicLong) that all threads can check for completion, and update when they have completed the activity.

Q2: It's definitely possible. You'd have set up a Runnable that could take your Shapes and the range of subset size to work on. But from what I can see, this is probably overkill: Task 2 (the part that you've done) is going to need much more processing power than Task 1, so you might as well just keep it the way you're doing it now

Please tell me if I've misread your question

Upvotes: 1

Related Questions