在一个线程完成任务后,如何告诉线程池中的其他线程停止?

时间:2017-03-15 18:16:35

标签: java multithreading concurrency java.util.concurrent

这是我的代码:

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);

    }
}

我的代码流程如下:

  1. 从名为par的整数ArrayList开始,遍历此集合中的每个元素(我们将调用A)

  2. 从par中删除A以获得B

  3. 查找大小为i的所有子集(范围为1到par.size())

  4. [多线程]对于大小为i的每个子集,在A中重新添加以获取新的集合C.然后找到删除时增加C得分最多的值。 [条件]如果该值为A,则从par中删除A并转到par中的下一个元素。如果没有为任何大小为i的子集删除A,请继续执行参数中的下一个元素。

  5. 我的目的是让每个线程使用其中一个子集并执行上面的 Multithreaded 步骤,直到其中一个线程符合 Condition 。我认为我正确地实现了这一点,但是因为我不熟悉并发编程,所以会很高兴第二眼。

    问题1:在上面的多线程步骤中,我怎样才能告诉线程池中的所有其他工作线程停止其任务并在单个线程遇到后返回到线程池中条件的?

    问题2:我有没有办法让多个线程同时处理不同大小的不同子集(因此一次有多个i值)并且有多个线程执行针对给定子集集的多线程步骤(这是我已经完成的)?基本上这就像将我的整个工作分成两个任务:任务1是查看大小为1,2,3 ... par.size()的子集集合,任务2是查看集合中的每个元素子集。

    感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

Q1:使用易失性静态变量(可能是易失性AtomicLong),所有线程都可以检查完成,并在完成活动时进行更新。

Q2:这绝对有可能。您已经设置了一个可以使用Shapes和子集大小范围的Runnable。但是从我所看到的情况来看,这可能是一种过度杀伤:任务2(你已经完成的部分)需要比任务1更多的处理能力,所以你也可以按照你的方式保持它现在

如果我误解了您的问题,请告诉我

答案 1 :(得分:0)

问题1:在上面的多线程步骤中,我如何告诉线程池中的所有其他工作线程停止其任务并在单个线程满足条件后返回到线程池? / p>

使用ExecutorService

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

执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果在给定的超时之前已经执行了任何操作。在正常或特殊退货时,未完成的任务将被取消。如果在此操作正在进行时修改了给定集合,则此方法的结果未定义。

问题2:我有没有办法让多个线程同时处理不同大小的不同子集(所以i的多个值一次)并且有多个线程执行上面的多线程步骤对于给定的一组子集(这是我已经完成的)?

你可以这样做。如果您在实施上述任何问题时遇到问题,请分享您的问题。即使您要等待所有任务的完成,也可以使用invokeAll。如果您想提高效果,可以使用ForkJoinPool