Jakarta ee 如何在JavaEE中构建递归树?

Jakarta ee 如何在JavaEE中构建递归树?,jakarta-ee,concurrency,managedthreadfactory,Jakarta Ee,Concurrency,Managedthreadfactory,这是我的伪代码: class Builder implements Callable<T> { T obj; ManagedExecutorService pool; Builder (T obj, ManagedExecutorService pool){ this.obj = obj; this.pool = pool; } T call(){ build(); } private void build(){

这是我的伪代码:

class Builder implements Callable<T> {
  T obj;
  ManagedExecutorService pool;

  Builder (T obj, ManagedExecutorService pool){
    this.obj = obj;
    this.pool = pool;
  }

  T call(){
    build();
  }

  private void build(){
        // skip if already traversed
        return isTraversed(obj);

        // call db and get obj's one-to-many relationships
        Collection<T> colOfChildObj = DbUtil.getChildrenPOJO(obj);
        for (<Collection>T childObj : colOfChildObj){
            this.pool.submit(new Builder(childObj, this.pool));
        }
        // set children as-is, when the submit above completes,
        // it will update childObj and thus will reflect
        // obj.childObj.itsChidren etc. For this though the caller
        // has to wait until all submits are processed 
        obj.setChildren(colOfChildObj); 
  }
}
然后,我的方法不会等待所有pool.submit(newbuilder(childObj,pool)),因此我的对象没有设置所有内容,并且是不完整的。我曾想过将pool.submit返回的所有期货放入一个阻塞队列中,但我不知道如何通知调用方我的树遍历已完成。当树遍历完成时,我确实有一个达到0的计数器,但是由于客户机正在提交一个顶级节点,我不知道如何让它在JavaEE中等待while(isCounter=0)-这是一个CPU占用


有什么建议吗?

我想我明白你想做什么。您可以只使用线程安全计数器,每次为给定节点创建和提交新任务时递增该计数器,并在该节点的任务终止时递减该计数器

在主线程中,等待一个锁,剩余的要处理的节点数为0。在每个任务中,您都会通知锁,以发出一个tack终止的信号

这是一个完整的例子。它从一棵树开始,其中每个节点都有一个名称,并将此树转换为另一棵树,其中每个节点都与原始名称连接在一起

public class Tree {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Node root = new Node("R");

        Node c1 = new Node("C1");
        Node c2 = new Node("C2");

        root.addChild(c1);
        root.addChild(c2);

        Node gc11 = new Node("GC11");
        Node gc12 = new Node("GC12");
        c1.addChild(gc11);
        c1.addChild(gc12);

        Node gc21 = new Node("GC11");
        Node gc22 = new Node("GC12");
        c2.addChild(gc21);
        c2.addChild(gc22);

        System.out.println("root = " + root);

        ExecutorService executor = Executors.newFixedThreadPool(4);
        final Object lock = new Object();
        final AtomicInteger remaining = new AtomicInteger(0);
        Future<Node> result = executor.submit(new HelloTask(root, null, executor, remaining, lock));

        synchronized (lock) {
            while (remaining.get() != 0) {
                lock.wait();
            }
        }

        Node helloRoot = result.get();

        System.out.println("helloRoot = " + helloRoot);

        executor.shutdown();
    }

    private static class HelloTask implements Callable<Node> {
        private final Node source;
        private final Node parent;
        private final ExecutorService executorService;
        private final Object lock;
        private final AtomicInteger remaining;

        public HelloTask(Node source, Node parent, ExecutorService executorService, AtomicInteger remaining, Object lock) {
            this.source = source;
            this.parent = parent;
            this.executorService = executorService;
            this.lock = lock;
            this.remaining = remaining;
            remaining.incrementAndGet();
        }

        @Override
        public Node call() throws Exception {
            // simulate some time
            Thread.sleep(1000L);
            Node result = new Node("Hello " + source.getName());
            if (parent != null) {
                parent.addChild(result);
            }
            for (Node child : source.getChildren()) {
                executorService.submit(new HelloTask(child, result, executorService, remaining, lock));
            }

            remaining.decrementAndGet();
            synchronized (lock) {
                lock.notifyAll();
            }
            return result;
        }
    }

    private static class Node {
        private final String name;
        private final List<Node> children = new CopyOnWriteArrayList<>();

        public Node(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public List<Node> getChildren() {
            return children;
        }

        public void addChild(Node child) {
            this.children.add(child);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(name);
            sb.append('\n');
            children.forEach(sb::append);
            return sb.toString();
        }
    }
}
公共类树{
公共静态void main(字符串[]args)引发ExecutionException、InterruptedException{
节点根=新节点(“R”);
节点c1=新节点(“c1”);
节点c2=新节点(“c2”);
根addChild(c1);
根addChild(c2);
节点gc11=新节点(“gc11”);
节点gc12=新节点(“gc12”);
c1.addChild(gc11);
c1.addChild(gc12);
节点gc21=新节点(“GC11”);
节点gc22=新节点(“GC12”);
c2.addChild(gc21);
c2.addChild(gc22);
System.out.println(“root=”+root);
ExecutorService executor=Executors.newFixedThreadPool(4);
最终对象锁=新对象();
最终AtomicInteger剩余=新的AtomicInteger(0);
未来结果=executor.submit(新HelloTask(root,null,executor,remaining,lock));
已同步(锁定){
while(剩余的.get()!=0){
lock.wait();
}
}
节点helloRoot=result.get();
System.out.println(“helloRoot=“+helloRoot”);
executor.shutdown();
}
私有静态类HelloTask实现了可调用{
私有最终节点源;
私有最终节点父节点;
私人最终执行服务;
私有最终对象锁;
剩余的私有最终原子;
公共HelloTask(节点源、节点父节点、ExecutorService ExecutorService、AtomicInteger剩余、对象锁){
this.source=源;
this.parent=parent;
this.executorService=executorService;
this.lock=锁;
剩余=剩余;
remaining.incrementAndGet();
}
@凌驾
公共节点调用()引发异常{
//模拟一段时间
睡眠(1000L);
节点结果=新节点(“Hello”+source.getName());
如果(父项!=null){
parent.addChild(结果);
}
对于(节点子节点:source.getChildren()){
提交(新HelloTask(子项、结果、executorService、剩余项、锁));
}
剩余。递减和获取();
已同步(锁定){
lock.notifyAll();
}
返回结果;
}
}
私有静态类节点{
私有最终字符串名;
private final List children=new CopyOnWriteArrayList();
公共节点(字符串名称){
this.name=名称;
}
公共字符串getName(){
返回名称;
}
公共列表getChildren(){
返回儿童;
}
公共void addChild(节点子节点){
this.children.add(child);
}
@凌驾
公共字符串toString(){
StringBuilder sb=新的StringBuilder();
某人(姓名);
sb.追加('\n');
孩子们。forEach(sb::append);
使某人返回字符串();
}
}
}

您能解释一下您的目标吗?标题表明您正在尝试构建一棵树。但是这个问题表明你正在尝试同时做一些事情(但是什么?)。你想达到什么目标?似乎您正在尝试处理来自多个线程的托管JPA实体。这已经是错误的:托管实体不是线程安全的。它们链接到的持久性上下文不是线程安全的。请查看我的更新,了解更多详细信息。不,这些不是托管对象,只是POJO。是的,您理解得正确。唯一的问题是我需要在JavaEE容器中运行它,所以根据规范,我不能调用lock.wait()或lock.notifyAll()操作。我也不能执行executor.shutdown();-我想这与同步(锁定)循环无关。有没有一种方法可以把它包装成一个未来?因此,不要使用synchronized(lock),而是使用result.get()-这反过来会解决树遍历完成问题?这里的关闭只是为了避免命令行演示无休止地运行。你不会在你的服务器上使用它。我认为您阅读规范时过于谨慎:以这种方式调用wait()和notify()不是问题。不超过例如,同步发送HTTP请求,从而阻塞直到响应返回。您不能只执行result.get(),因为这将在处理根节点后立即返回,当子节点仍在处理时,只想在java ee环境中添加我必须使用的:new ThreadPoolExecutor(corePoolSize、maxPoolSize、keepAliveTime、TimeUnit.SECONDS、workQueue、getThreadFactory())-这样未知深度的递归不会在线程上耗尽(而是保持
public class Tree {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Node root = new Node("R");

        Node c1 = new Node("C1");
        Node c2 = new Node("C2");

        root.addChild(c1);
        root.addChild(c2);

        Node gc11 = new Node("GC11");
        Node gc12 = new Node("GC12");
        c1.addChild(gc11);
        c1.addChild(gc12);

        Node gc21 = new Node("GC11");
        Node gc22 = new Node("GC12");
        c2.addChild(gc21);
        c2.addChild(gc22);

        System.out.println("root = " + root);

        ExecutorService executor = Executors.newFixedThreadPool(4);
        final Object lock = new Object();
        final AtomicInteger remaining = new AtomicInteger(0);
        Future<Node> result = executor.submit(new HelloTask(root, null, executor, remaining, lock));

        synchronized (lock) {
            while (remaining.get() != 0) {
                lock.wait();
            }
        }

        Node helloRoot = result.get();

        System.out.println("helloRoot = " + helloRoot);

        executor.shutdown();
    }

    private static class HelloTask implements Callable<Node> {
        private final Node source;
        private final Node parent;
        private final ExecutorService executorService;
        private final Object lock;
        private final AtomicInteger remaining;

        public HelloTask(Node source, Node parent, ExecutorService executorService, AtomicInteger remaining, Object lock) {
            this.source = source;
            this.parent = parent;
            this.executorService = executorService;
            this.lock = lock;
            this.remaining = remaining;
            remaining.incrementAndGet();
        }

        @Override
        public Node call() throws Exception {
            // simulate some time
            Thread.sleep(1000L);
            Node result = new Node("Hello " + source.getName());
            if (parent != null) {
                parent.addChild(result);
            }
            for (Node child : source.getChildren()) {
                executorService.submit(new HelloTask(child, result, executorService, remaining, lock));
            }

            remaining.decrementAndGet();
            synchronized (lock) {
                lock.notifyAll();
            }
            return result;
        }
    }

    private static class Node {
        private final String name;
        private final List<Node> children = new CopyOnWriteArrayList<>();

        public Node(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public List<Node> getChildren() {
            return children;
        }

        public void addChild(Node child) {
            this.children.add(child);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(name);
            sb.append('\n');
            children.forEach(sb::append);
            return sb.toString();
        }
    }
}