ExecutionException:NoSuchElementException - 为什么会引发它?

时间:2014-01-11 20:40:55

标签: java exception java.util.concurrent

- 主要编辑:此处包含所有代码 -

package main;

import tree.BinaryTreeAdder;
import tree.BinaryTreeAdderImpl;
import tree.Node;
import tree.NodeImpl;

public class MainClass {

    private static Node treeBuilder() {
        NodeImpl n0 = new NodeImpl(0);
        NodeImpl n1 = new NodeImpl(1);
        NodeImpl n2 = new NodeImpl(2);
        NodeImpl n3 = new NodeImpl(3);
        NodeImpl n4 = new NodeImpl(4);
        NodeImpl n5 = new NodeImpl(5);
        NodeImpl n6 = new NodeImpl(6);
        NodeImpl n7 = new NodeImpl(7);
        NodeImpl n8 = new NodeImpl(8);
        NodeImpl n9 = new NodeImpl(9);
        NodeImpl n10 = new NodeImpl(10);
        n0.setSx(n1);
        n0.setDx(n2);
        n1.setSx(n3);
        n1.setDx(n4);
        n2.setSx(n5);
        n2.setDx(n6);
        n3.setSx(n7);
        n3.setDx(n8);
        n4.setSx(n9);
        n4.setDx(n10);
        return n0;
    }

    public static void main(String[] args) {
        Node n0 = treeBuilder();
        BinaryTreeAdder adder = new BinaryTreeAdderImpl();
        int result = adder.computeOnerousSum(n0);
        System.out.println(result);
    }
}

package processor;

public class FakeProcessor implements OnerousProcessor {
    public final static int MIN_COUNT = 1000;
    private int max;
    private java.util.Random random;
    public FakeProcessor(int max) {
        this.max = max;
        this.random = new java.util.Random();
    }
    public int onerousFunction(int value) {
        int r = this.random.nextInt(this.max);
        int n = Math.max(MIN_COUNT, r); // non meno di MIN_COUNT
        // useless but onerous
        for(int counter=0; counter<n; counter++) {
            r = this.random.nextInt(this.max); // maschera casuale
            r = r ^ this.random.nextInt(this.max); // inverti i bit
            r = r ^ this.random.nextInt(this.max); // due volte
        }
        return value; // n.b. value risulta invariato
    }
}

package processor;

public interface OnerousProcessor {
    public int onerousFunction(int value);
}

package thread;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.Callable;
import processor.OnerousProcessor;
import tree.Node;

public class ComputeTask implements Callable<Integer> {
    private OnerousProcessor processor;
    private BlockingDeque<Node> buffer;

    public ComputeTask(BlockingDeque<Node> buffer, OnerousProcessor processor) {
        this.buffer = buffer;
        this.processor = processor;
    }

    @Override
    public Integer call() throws Exception {
        Node currentNode = this.buffer.pop();
        Integer value = new Integer(this.processor.onerousFunction(currentNode.getValue()));
        if(currentNode.getSx() != null) {
            this.buffer.add(currentNode.getSx());
        }
        if(currentNode.getDx() != null) {
            this.buffer.add(currentNode.getDx());
        }
        return value;
    }

}

package tree;

public interface BinaryTreeAdder {
    public int computeOnerousSum(Node root);
}

package tree;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

import processor.FakeProcessor;
import processor.OnerousProcessor;
import thread.ComputeTask;
public class BinaryTreeAdderImpl implements BinaryTreeAdder {
    private BlockingDeque<Node> buffer;
    private ExecutorService executor;

    public BinaryTreeAdderImpl(/*Node root*/) {
        this.buffer = new LinkedBlockingDeque<Node>();
        //buffer.add(root);
        this.executor = Executors.newFixedThreadPool(8);
    }

    @Override
    public int computeOnerousSum(Node root) {
        OnerousProcessor processor = new FakeProcessor(1000);
        this.buffer.addLast(root);
        List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
        while(buffer.size() != 0) {
            Callable<Integer> computeThis = new ComputeTask(this.buffer, processor);
            futures.add(this.executor.submit(computeThis));
        }
        int result = 0;
        for(Future<Integer> f : futures) {
            try {
                result += f.get().intValue();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

}

package tree;

public interface Node {
    Node getSx(); //null se non esiste figlio sinistro
    Node getDx(); //null se non esiste figlio destro
    int getValue(); //restituisce un intero associato al nodo
}

package tree;

public class NodeImpl implements Node {
    private int value;
    private Node leftChild;
    private Node rightChild;

    public NodeImpl(int value) {
        this.value = value;
        this.leftChild = null;
        this.rightChild = null;
    }

    @Override
    public Node getSx() {
        return this.leftChild;
    }

    @Override
    public Node getDx() {
        return this.rightChild;
    }

    @Override
    public int getValue() {
        return this.value;
    }

    public void setSx(Node leftChild) {
        this.leftChild = leftChild;
    }

    public void setDx(Node rightChild) {
        this.rightChild = rightChild;
    }

}

---代码结束---

Hello StackOverflow世界。我需要你的帮助来解决(可能很简单,但仍然不清楚)问题!

我正在构建一个简单的,仅客户端的Java应用程序,以便使用java.util.concurrent和threads进行一些练习。在这个项目中,我必须扫描一棵树,对节点中包含的int值进行一些繁重的计算,并总结得到的值,显示结果。我正在使用轻量级可执行框架。

以下方法来自ComputeTask类,稍后将在引发异常的方法中使用。我不知道它是否相关,但它是:

    public Integer call() throws Exception {
    Node currentNode = this.buffer.pop();
    Integer value = new Integer(this.processor.onerousFunction(currentNode.getValue()));
    if(currentNode.getSx() != null) {
        this.buffer.add(currentNode.getSx());
    }
    if(currentNode.getDx() != null) {
        this.buffer.add(currentNode.getDx());
    }
    return value;
}

以下是引发异常的方法:

    public int computeOnerousSum(Node root) {
    OnerousProcessor processor = new FakeProcessor(1000);
    this.buffer.addLast(root);
    List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
    while(buffer.size() != 0) {
        Callable<Integer> computeThis = new ComputeTask(this.buffer, processor);
        futures.add(this.executor.submit(computeThis));
    }
    int result = 0;
    for(Future<Integer> f : futures) {
        try {
        /*exception is raised here*/    result += f.get().intValue();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
    return result;
}

其余代码非常简单。

我试图调试,并且发生了一件奇怪的事情:如果我在没有插入前一个方法的调用的情况下进行调试,我会得到堆栈跟踪并且结果为0。 如果我进入computeOnerousSum代替,我可以看到每次都执行catch方法,奇怪的是,结果被正确地求和,直到它达到正确的值55,最后正确打印(在main中)。 / p>

你知道为什么我在调试时能看到正确的行为,更重要的是,为什么该方法仍然会引发NoSuchElementException(这是一个ExecutionException)?

提前谢谢大家, 如果你发现我的解释不清楚或不完整,请问我。


正如所建议的,这是堆栈跟踪!

java.util.concurrent.ExecutionException: java.util.NoSuchElementException
    at java.util.concurrent.FutureTask.report(Unknown Source)
    at java.util.concurrent.FutureTask.get(Unknown Source)
    at tree.BinaryTreeAdderImpl.computeOnerousSum(BinaryTreeAdderImpl.java:31)
    at main.MainClass.main(MainClass.java:38)
Caused by: java.util.NoSuchElementException
    at java.util.concurrent.LinkedBlockingDeque.removeFirst(Unknown Source)
    at java.util.concurrent.LinkedBlockingDeque.pop(Unknown Source)
    at thread.ComputeTask.call(ComputeTask.java:19)
    at thread.ComputeTask.call(ComputeTask.java:1)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
java.util.concurrent.ExecutionException: java.util.NoSuchElementException
    at java.util.concurrent.FutureTask.report(Unknown Source)
    at java.util.concurrent.FutureTask.get(Unknown Source)
    at tree.BinaryTreeAdderImpl.computeOnerousSum(BinaryTreeAdderImpl.java:31)
    at main.MainClass.main(MainClass.java:38)
Caused by: java.util.NoSuchElementException
    at java.util.concurrent.LinkedBlockingDeque.removeFirst(Unknown Source)
    at java.util.concurrent.LinkedBlockingDeque.pop(Unknown Source)
    at thread.ComputeTask.call(ComputeTask.java:19)
    at thread.ComputeTask.call(ComputeTask.java:1)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
java.util.concurrent.ExecutionException: java.util.NoSuchElementException
    at java.util.concurrent.FutureTask.report(Unknown Source)
    at java.util.concurrent.FutureTask.get(Unknown Source)
    at tree.BinaryTreeAdderImpl.computeOnerousSum(BinaryTreeAdderImpl.java:31)
    at main.MainClass.main(MainClass.java:38)
Caused by: java.util.NoSuchElementException
    at java.util.concurrent.LinkedBlockingDeque.removeFirst(Unknown Source)
    at java.util.concurrent.LinkedBlockingDeque.pop(Unknown Source)
    at thread.ComputeTask.call(ComputeTask.java:19)
    at thread.ComputeTask.call(ComputeTask.java:1)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
java.util.concurrent.ExecutionException: java.util.NoSuchElementException
    at java.util.concurrent.FutureTask.report(Unknown Source)
    at java.util.concurrent.FutureTask.get(Unknown Source)
    at tree.BinaryTreeAdderImpl.computeOnerousSum(BinaryTreeAdderImpl.java:31)
    at main.MainClass.main(MainClass.java:38)
Caused by: java.util.NoSuchElementException
    at java.util.concurrent.LinkedBlockingDeque.removeFirst(Unknown Source)
    at java.util.concurrent.LinkedBlockingDeque.pop(Unknown Source)
    at thread.ComputeTask.call(ComputeTask.java:19)
    at thread.ComputeTask.call(ComputeTask.java:1)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
0

0 个答案:

没有答案