未来对象的多重并发问题

时间:2014-04-30 00:24:16

标签: java multithreading concurrency phaser

我正在尝试生成一些线程,并在执行时将它们放在List中。当他们完成处理时,我想收集他们的结果进行演示。这样我可以有一个包含许多线程的列表,然后一旦它们可用,我可以调用future.get并使用它们的回调信息。

出于某种原因,我遗漏了很多结果。当我逐步完成代码时,f.get()正在被传递,当它不应该是,而我无法找出原因。

我的代码如下:

     public class ThreadTesterRunner {
            static List<Integer> randoms = new ArrayList<>();

            public static void main(String[] args) throws InterruptedException {
                final Phaser cb = new Phaser();
                ThreadRunner tr = new ThreadRunner(cb);
                Thread t = new Thread(tr, "Thread Runner");
                t.start();

                boolean process = true;
                // wait until all threads process, then print reports
                while (process){
                    if(tr.isFinished()){
                        System.out.println("Print metrics");
                        process = false;

                    }
                    Thread.sleep(1000);
                }
            }
        }


      class ThreadRunner implements Runnable {
            private ExecutorService executorService = Executors.newFixedThreadPool(10);
            private final Phaser barrier;
            private boolean finished=false;

            public ThreadRunner(Phaser phaser) {this.barrier = phaser;}

            public void run(){
                try {
                    List<Future<Integer>> list = new ArrayList<>();
                    boolean stillLoop = true; int i = 0;

                    final Phaser p = this.barrier;
                    Callable<Integer> task = new Callable<Integer>() {
                           public Integer call() throws Exception {
                               return new Reader().doRun(p);
                           }
                    };

                    List<Integer> randoms = new ArrayList<>();
                    Integer size;
                    while (stillLoop){
                        System.out.println("i "+i);
                        list.add(executorService.submit(task));

                        for(Future<Integer> f: list){
                            if(f.isDone()){
                                size = f.get();
                                System.out.println("size "+size);
                                list.remove(f);
                            } else {
                                  // keep processing
                            }
                        }
                        if(i == 2){
                            System.out.println("breaking out of loop");
                            stillLoop = false;
                        }
                        i++;
                    }
                    this.barrier.awaitAdvance(0);
                    this.finished=true;
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
            public boolean isFinished(){
                return this.finished;
            }
        }

class Reader {

    private Phaser readBarrier;
    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    public Reader() {
    }    

    Random randomGenerator = new Random();

    public Integer doRun(Phaser phaser) throws Exception {
        phaser.register();
        this.readBarrier = phaser;
        System.out.println("Reading...");
        int i;

        int r = randomGenerator.nextInt(100);
        System.out.println("r "+r);
        ThreadTesterRunner.randoms.add(r);

        int a = this.readBarrier.arrive();
        return r; //i;
    }
}

有任何想法可能会发生这种情况吗?

编辑:

好吧,我想我已经启动并运行了:

class ThreadRunner implements Runnable {
    // static int timeOutTime = 2;
    private ExecutorService executorService = Executors.newFixedThreadPool(10);
    private final Phaser barrier;
    private boolean finished = false;

    public ThreadRunner(Phaser phaser) {
        this.barrier = phaser;
    }

    public void run() {
        try {
            List<Future<Integer>> list = new CopyOnWriteArrayList<>(); 
            boolean stillLoop = true;
            int i = 0;

            final Phaser p = this.barrier;
            Callable<Integer> readerTask = new Callable<Integer>() {
                public Integer call() throws Exception {
                    return new Reader().doRun(p);
                }
            };

            List<Integer> randoms = new ArrayList<>();
            Integer size;
            while (stillLoop) {
                if (i <= 2) {
                    list.add(executorService.submit(readerTask));
                }

                if (!list.isEmpty()) {
                    for (Future<Integer> f : list) {
                        if (f.isDone()) {
                            size = f.get();
                            randoms.add(size);
                            System.out.println("Process read with a size of "+ size);
                            list.remove(f);
                        } else {
                            // System.out.println("skipping");
                        }
                    }
                } else {
                    stillLoop = false;
                }
                i++;
            }
            System.out.println("at barrier waiting");
            this.barrier.awaitAdvance(0);
            System.out.println("barrier crossed");
            this.finished = true;
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    public boolean isFinished() {
        return this.finished;
    }
}

1 个答案:

答案 0 :(得分:0)

结果: 我0 我1 我2 打破循环 读... 读... 13 44 读... 78 打印指标

我将ArrayList更改为Vector,因为ArrayList不是线程安全的,最终会导致ConcurrentModificationException。

以上输出是您所期望的吗?