繁体   English   中英

为什么此CompletableFuture无法与共享的ExecutorService一起执行?

[英]Why does this CompletableFuture not execute with a shared ExecutorService?

我正在研究一种数据流语言的想法,并且尝试使用执行程序服务将可用线程数限制为系统上的内核数,并创建一个共享线程池。

 ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
 Function a = new Function("A", service);
 Function b = new Function("B", service);
 Function c = new Function("C", service);
 a.addObserver(b);
 a.addObserver(c);
 a.change()

A发生了更改,导致其调用了evaluate() ,然后B和C收到通知,他们需要更新并且这样做。

Function.java我有:

 public class Function implements Func{
    private boolean isComplete;
    private Set<Func> dependsOn;
    private Set<Func> observedBy;
    private ExecutorService service;

    public Function(String name, ExecutorService service){
        observedBy = new HashSet<>();
        dependsOn = new HashSet<>();
        this.isComplete = false;
        this.service = service;
    }

    public void addObserver(Func f){
        observedBy.add(f);
        f.addDependency(this);
    }

    private void evaluate() {
        boolean match = dependsOn.stream().allMatch(Func::isComplete);

        if (match) {
            this.isComplete = false;

            // inform each observer that I'm about to start to evaluate
            observedBy.forEach(func -> func.onDependentEvaluate(this));

            CompletableFuture.runAsync(() -> {
                try {
                    System.out.println("Doing some work");
                    int sleepTime = (int) (Math.random() * 5000);
                    System.out.println("Working for " + sleepTime);
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, service).thenRun(this::onComplete);
        }
    }

    public void addDependency(Func f){
        dependsOn.add(f);
    }

    @Override
    public void change() {;
        evaluate();
    }

    @Override
    public void onComplete() {
        this.isComplete = true;
        observedBy.forEach((f) -> f.onDependentComplete(this));
    }

    @Override
    public void onDependentEvaluate(Func f) {
    }

    @Override
    public void onDependentComplete(Func func){
        evaluate();
    }

    @Override
    public boolean isComplete() {
        return this.isComplete;
    }
}

当我将service传递给runAsync ,只有A执行。 如果我不传递service ,而CompletableFuture使用ForkJoin.commonPool,则该图将按我的期望执行。 有其他共享ExecutorService吗? 有什么想法为什么下一个期货不被执行?

您的问题比您想象的要简单得多。 tl; dr唯一的问题是您没有关闭ExecutorService ,因此程序不会终止。

加长版:在我的环境中,该程序按预期运行,并且任务BC实际上可以运行。 我已经重构了您的代码,以允许我创建AbstractFunction ,使我可以覆盖Function实际执行的行为,例如

public abstract class AbstractFunction implements Func {
  protected boolean isComplete;
  protected Set<Func> dependsOn;
  protected Set<Func> observedBy;
  protected ExecutorService service;
  protected String name;

  public AbstractFunction(String name, ExecutorService service) {
    observedBy = new HashSet<>();
    dependsOn = new HashSet<>();
    this.isComplete = false;
    this.service = service;
    this.name = name;
  }

  public void addObserver(Func f) {
    observedBy.add(f);
    f.addDependency(this);
  }

  public void addDependency(Func f) {
    dependsOn.add(f);
  }

  @Override
  public void onComplete() {
    this.isComplete = true;
    observedBy.forEach((f) -> f.onDependentComplete(this));
  }

  @Override
  public boolean isComplete() {
    return this.isComplete;
  }

  @Override
  public void change() { }

  @Override
  public void onDependentEvaluate(Func f) { }

  @Override
  public void onDependentComplete(Func func) { }
}

因此,您原来的(实际上未更改的) Function现在是这样的:

public class Function extends AbstractFunction implements Func {
  public Function(String name, ExecutorService service) {
    super(name, service);
  }

  protected void evaluate() {
    boolean match = dependsOn.stream().allMatch(Func::isComplete);

    if (match) {
      this.isComplete = false;

      // inform each observer that I'm about to start to evaluate
      observedBy.forEach(func -> func.onDependentEvaluate(this));

      CompletableFuture.runAsync(() -> {
        try {
          System.out.println("Doing some work");
          int sleepTime = (int) (Math.random() * 5000);
          System.out.println("Working for " + sleepTime);
          Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
          System.out.println("I was interrupted, my name is: " + name);
          e.printStackTrace();
        }
      }, service).thenRun(this::onComplete);
    }
  }

  @Override
  public void change() {
    evaluate();
  }

  @Override
  public void onDependentComplete(Func f) {
    evaluate();
  }
}

给定这个新结构,我创建一个ShutdownFunc来侦听并在"C"完成时关闭执行程序服务,即

public class ShutdownFunc extends AbstractFunction {
  public ShutdownFunc(String name, ExecutorService service) {
    super(name, service);
  }

  @Override
  public void onDependentComplete(Func f) {
    System.out.println("Shutting down the system");
    try {
      service.shutdown();
      service.awaitTermination(5, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

当然主要:

public class Main {
  public static void main(String... args) {
    ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime()
        .availableProcessors());
    Function a = new Function("A", service);
    Function b = new Function("B", service);
    Function c = new Function("C", service);
    a.addObserver(b);
    a.addObserver(c);

    Func d = new ShutdownFunc("D", service);
    c.addObserver(d);

    a.change();
  }
}

输出:

Doing some work
Working for 4315
Doing some work
Working for 2074
Doing some work
Working for 2884
Shutting down the system

程序正确等待完成,然后正常终止。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM