是否有更好的方法来使用与AtomicInteger连接的wait / notify

时间:2015-07-07 12:43:05

标签: java multithreading recursion wait notify

我有这样的代码:

public class RecursiveQueue {
    //@Inject
    private QueueService queueService;
    public static void main(String[] args) {
        RecursiveQueue test = new RecursiveQueue();
        test.enqueue(new Node("X"), true);
        test.enqueue(new Node("Y"), false);
        test.enqueue(new Node("Z"), false);
    }

    private void enqueue(final Node node, final boolean waitTillFinished) {
        final AtomicLong totalDuration = new AtomicLong(0L);
        final AtomicInteger counter = new AtomicInteger(0);

        AfterCallback callback= new AfterCallback() {
            @Override
            public void onFinish(Result result) {
                for(Node aNode : result.getChildren())  {
                    counter.incrementAndGet();
                    queueService.requestProcess(aNode, this);
                }

                totalDuration.addAndGet(result.getDuration());
                if(counter.decrementAndGet() <= 0) { //last one
                    System.out.println("Processing of " + node.toString() + " has finished in " + totalDuration.get() + " ms");
                    if(waitTillFinished) {
                        counter.notify();
                    }
                }
            }
        };

        counter.incrementAndGet();
        queueService.requestProcess(node, callback);
        if(waitTillFinished) {
            try {
                counter.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

想象一下,有一个queueService使用阻塞队列和很少的消费者线程来处理节点=调用DAO来获取节点的子节点(它是一棵树)。 所以requestProcess方法只是将节点排队并且不阻塞。

是否有更好/安全的方法可以避免在此示例中使用wait / notify? 根据一些调查结果,我可以使用Phaser(但我在java 6上工作)或条件(但我没有使用锁)。

3 个答案:

答案 0 :(得分:3)

  • 您的示例中没有synchronized任何内容。除非o.wait()阻止,否则您无法致电o.notify()synchronized(o) {...}

  • 您对wait()的电话不在循环中。这可能不会在您的JVM中发生,但语言规范允许wait()过早返回(这被称为虚假唤醒)更一般地说,总是优秀的做法使用循环是因为它是一种熟悉的设计模式。 while语句的费用不会超过if,而 应该拥有它,因为虚假唤醒的可能性,并且你绝对必须< / em>让它处于多消费者的情况下,所以你不妨总是这样写。

  • 由于您必须使用synchronized块才能使用wait()notify(),因此可能没有理由使用Atomic任何内容。

  • 这个&#34;递归&#34;事情看起来非常复杂,回调会向队列中添加更多项目。这有多深?

答案 1 :(得分:0)

我认为您正在寻找CountDownLatch

答案 2 :(得分:0)

你实际上使用了锁,或者让我们这样说,如果你试图像James指出的那样尝试使用wait / notify,你应该使用它们。由于您无法使用Java 1.6和ForkJoin或Phaser,因此选择正确实现wait / notify或使用带有显式锁定的Condition。这将取决于您的个人喜好。

另一种方法是尝试重构您的算法,以便您首先了解执行所需的整个步骤集。但这并不总是可能的。